public override void Enumerate(IMemberCompletionAcceptor acceptor) { if (acceptor == null) throw ExceptionBuilder.ArgumentNull("acceptor"); // Report all columns accessible by the table ref. TableRefBinding tableRefBinding = new TableRefBinding(null, _tableBinding, _correlationName); foreach (ColumnBinding columnBinding in _tableBinding.Columns) { ColumnRefBinding columnRefBinding = new ColumnRefBinding(tableRefBinding, columnBinding); acceptor.AcceptColumnRef(columnRefBinding); } // Now contribute any methods accessible by the row type. IMethodProvider methodProvider = _scope.DataContext.MetadataContext.MethodProviders[_tableBinding.RowType]; if (methodProvider != null) { MethodBinding[] methods = methodProvider.GetMethods(_tableBinding.RowType); foreach (MethodBinding methodBinding in methods) acceptor.AcceptMethod(methodBinding); } }
public MetaInfo(ColumnRefBinding[] columnDependencies, TableRefBinding[] tableDependencies, bool containsSingleRowSubselects, bool containsExistenceSubselects) { _columnDependencies = columnDependencies; _tableDependencies = tableDependencies; _containsSingleRowSubselects = containsSingleRowSubselects; _containsExistenceSubselects = containsExistenceSubselects; }
private static JoinOrder GetBestJoinOrder(TableRefBinding[] tables, JoinCondition[] joinConditions, ICollection<ExpressionNode> andParts) { // Compute all join orders JoinOrderGenerator generator = new JoinOrderGenerator(joinConditions, tables); JoinOrder[] allJoinOrders = generator.GenerateAll(); // Compute best join order JoinOrder bestJoinOrder = GetBestJoinOrder(allJoinOrders, andParts, tables); return bestJoinOrder; }
private static ColumnRefBinding CreateRowColumnRefBinding(TableRefBinding tableRefBinding) { RowColumnBinding rowColumnBinding = new RowColumnBinding(tableRefBinding.TableBinding); ColumnRefBinding rowColumnRefBinding = new ColumnRefBinding(tableRefBinding, rowColumnBinding); RowBufferEntry rowColumnBufferEntry = new RowBufferEntry(rowColumnRefBinding.ColumnBinding.DataType); rowColumnBufferEntry.Name = rowColumnRefBinding.TableRefBinding.Name; ColumnValueDefinition rowColumnValueDefinition = new ColumnValueDefinition(); rowColumnValueDefinition.Target = rowColumnBufferEntry; rowColumnValueDefinition.ColumnRefBinding = rowColumnRefBinding; rowColumnRefBinding.ValueDefinition = rowColumnValueDefinition; return rowColumnRefBinding; }
private static JoinOrder GetBestJoinOrder(JoinOrder[] orders, ICollection<ExpressionNode> andParts, TableRefBinding[] tables) { // OK, now we try to find the best join order. // // To choose the best join order we will use a point system and score each possibility. // The more points a possibility has the better it is. // // To ensure we exclude as much rows as possible and as early as possible // we will use the count of conditions applicable to each combinations. // // A condition is said to be applicable if all referenced tables are already // joined. For example if we have to join four tables T1, T2, T3, T4. Accordding to // the join order T1 -> T2 -> T3 -> T4 the condition c is said to be applicable // at join index 0 if it only references columns of table T1, at index 1 if it // only references columns of tables T1 and T2 and so on. // Determine minimal count of cross joins int minCrossJoinCount = int.MaxValue; for (int i = 0; i < orders.Length; i++) { int crossJoinCount = GetCrossJoinCount(orders[i]); if (crossJoinCount < minCrossJoinCount) minCrossJoinCount = crossJoinCount; } int[] points = new int[orders.Length]; for (int i = 0; i < orders.Length; i++) { points[i] = GetJoinOrderScore(orders[i], andParts, tables); if (GetCrossJoinCount(orders[i]) > minCrossJoinCount) { // If the current join order uses more cross joins than // the minimal one we reject this join order by setting // its score to minus one. points[i] = -1; } } Array.Sort(points, orders); JoinOrder bestJoinOrder = orders[orders.Length - 1]; return bestJoinOrder; }
private static ColumnRefBinding CreateRowColumnRefBinding(TableRefBinding tableRefBinding) { RowColumnBinding rowColumnBinding = new RowColumnBinding(tableRefBinding.TableBinding); ColumnRefBinding rowColumnRefBinding = new ColumnRefBinding(tableRefBinding, rowColumnBinding); RowBufferEntry rowColumnBufferEntry = new RowBufferEntry(rowColumnRefBinding.ColumnBinding.DataType); rowColumnBufferEntry.Name = rowColumnRefBinding.TableRefBinding.Name; ColumnValueDefinition rowColumnValueDefinition = new ColumnValueDefinition(); rowColumnValueDefinition.Target = rowColumnBufferEntry; rowColumnValueDefinition.ColumnRefBinding = rowColumnRefBinding; rowColumnRefBinding.ValueDefinition = rowColumnValueDefinition; return(rowColumnRefBinding); }
void IErrorReporter.InvalidRowReference(SourceRange sourceRange, TableRefBinding derivedTableRef) { string message = String.Format(CultureInfo.CurrentCulture, Resources.InvalidRowReference, derivedTableRef.Name); HandleError(sourceRange, ErrorId.InvalidRowReference, message); }
void IErrorReporter.AmbiguousTableRef(SourceRange sourceRange, Identifier identifier, TableRefBinding[] candidates) { string message = String.Format(CultureInfo.CurrentCulture, Resources.AmbiguousTableRef, identifier, FormattingHelpers.FormatBindingList(candidates)); HandleError(sourceRange, ErrorId.AmbiguousTableRef, message); }
public NullRejectionChecker(TableRefBinding nullableTableRefBinding) { _nullableTableRefBinding = nullableTableRefBinding; }
public void AcceptRelation(TableRefBinding parentTableRef, TableRefBinding childTableRef, TableRelation relation) { }
private ColumnRefBinding ResolveColumnRef(TableRefBinding tableRef, SourceRange sourceRange, Identifier identifier) { QueryScope lookupScope = tableRef.Scope; ColumnRefBinding[] candidates = lookupScope.FindColumnRef(tableRef, identifier); if (candidates == null || candidates.Length == 0) return null; if (candidates.Length > 1) ErrorReporter.AmbiguousColumnRef(sourceRange, identifier, candidates); return candidates[0]; }
public void SwapSides() { ExpressionNode oldLeftExpression = _leftExpression; TableRefBinding oldLeftTable = _leftTable; _op = SwapJoinOperator(_op); _leftExpression = _rightExpression; _leftTable = _rightTable; _rightExpression = oldLeftExpression; _rightTable = oldLeftTable; }
public override AlgebraNode VisitTableAlgebraNode(TableAlgebraNode node) { TableRefBinding oldTableRefBinding = node.TableRefBinding; TableRefBinding newTableRefBinding = new TableRefBinding(oldTableRefBinding.Scope, oldTableRefBinding.TableBinding, oldTableRefBinding.Name); List<ColumnValueDefinition> definedValues = new List<ColumnValueDefinition>(); for (int i = 0; i < newTableRefBinding.ColumnRefs.Length; i++) { definedValues.Add(newTableRefBinding.ColumnRefs[i].ValueDefinition); RowBufferEntry oldRowBufferEntry = oldTableRefBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry newRowBufferEntry = newTableRefBinding.ColumnRefs[i].ValueDefinition.Target; _rowBufferMappings.Add(oldRowBufferEntry, newRowBufferEntry); } node.TableRefBinding = newTableRefBinding; node.DefinedValues = definedValues.ToArray(); return node; }
public void AcceptTableRef(TableRefBinding tableRef) { }
public JoinOrderGenerator(JoinCondition[] joinConditions, TableRefBinding[] tables) { _joinConditions = joinConditions; _tables = tables; }
public void AcceptTableRef(TableRefBinding tableRef) { Add(tableRef.Name, tableRef.GetFullName(), "TABLE REF", TABLE_REF_IMG_INDEX); }
private static ExpressionNode ExtractConditionsApplicableToTable(IDictionary<RowBufferEntry, ColumnValueDefinition> introducedColumns, IList<ExpressionNode> conditionList, TableRefBinding tableRefBinding) { List<ExpressionNode> applicableConditionList = new List<ExpressionNode>(); for (int i = conditionList.Count - 1; i >= 0; i--) { ExpressionNode condition = conditionList[i]; RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(condition); bool dependentOnOtherTable = false; foreach (RowBufferEntry rowBufferEntry in rowBufferEntries) { ColumnValueDefinition columnValueDefinition; if (introducedColumns.TryGetValue(rowBufferEntry, out columnValueDefinition)) { if (columnValueDefinition.ColumnRefBinding.TableRefBinding != tableRefBinding) { dependentOnOtherTable = true; break; } } } if (!dependentOnOtherTable) { conditionList.RemoveAt(i); applicableConditionList.Add(condition); } } if (applicableConditionList.Count == 0) return null; ExpressionNode[] applicableConditions = applicableConditionList.ToArray(); return AstUtil.CombineConditions(LogicalOperator.And, applicableConditions); }
private void WriteTableRef(TableRefBinding tableRefBinding) { _xmlWriter.WriteAttributeString("table", tableRefBinding.TableBinding.Name); _xmlWriter.WriteAttributeString("tableRef", tableRefBinding.Name); }
public ColumnRefBinding(TableRefBinding tableRefBinding, ColumnBinding columnBinding) { _tableRefBinding = tableRefBinding; _columnBinding = columnBinding; }
private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding) { // Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times. // Since same row buffer entries means that the underlying data will be stored in the same physical data slot this // will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that // operates on the same column will always compare data coming from the same join side (and therefor will always // evaluate to true). // // Some notes on the implementation: // // 1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough; // instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc. // 2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions // are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same // expression AST instances. That means that replacing the row buffers leads to failure. // HACK: This is a workaround for issue 2. However, // I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query. algebrizedCte = (AlgebraNode) algebrizedCte.Clone(); CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer(); cteTableDefinedValuesReinitializer.Visit(algebrizedCte); RowBufferEntry[] outputList = algebrizedCte.OutputList; int skipRecursionLevel = commonTableBinding.IsRecursive ? 1 : 0; // Rename the query columns to the CTE columns List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedCte; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); return computeScalarAlgebraNode; }
void IErrorReporter.TableRefInaccessible(TableRefBinding tableRefBinding) { string message = String.Format(CultureInfo.CurrentCulture, Resources.TableRefInaccessible, tableRefBinding.Name, tableRefBinding.TableBinding.Name); HandleError(ErrorId.TableRefInaccessible, message); }
void IErrorReporter.UndeclaredColumn(SourceRange sourceRange, TableRefBinding tableRefBinding, Identifier identifier) { string message = String.Format(CultureInfo.CurrentCulture, Resources.UndeclaredColumn, tableRefBinding.Name, identifier); HandleError(sourceRange, ErrorId.UndeclaredColumn, message); }
public void AcceptRelation(TableRefBinding parentBinding, TableRefBinding childBinding, TableRelation relation) { ColumnBindingCollection parentColumns; if (parentBinding.TableBinding == relation.ParentTable) parentColumns = relation.ParentColumns; else parentColumns = relation.ChildColumns; ColumnBindingCollection childColumns; if (childBinding.TableBinding == relation.ChildTable) childColumns = relation.ChildColumns; else childColumns = relation.ParentColumns; // Item in member list: // ~~~~~~~~~~~~~~~~~~~~ // parentRef(col1, col2) ---> childRef(col1, col2) StringBuilder sb = new StringBuilder(); sb.Append(parentBinding.Name); sb.Append(" ("); for (int i = 0; i < relation.ColumnCount; i++) { if (i > 0) sb.Append(", "); sb.Append(parentColumns[i].Name); } sb.Append(") ---> "); sb.Append(childBinding.Name); sb.Append(" ("); for (int i = 0; i < relation.ColumnCount; i++) { if (i > 0) sb.Append(", "); sb.Append(childColumns[i].Name); } sb.Append(")"); string name = sb.ToString(); sb.Length = 0; // Description: // ~~~~~~~~~~~~ // Relation <b>parentTable parentRef</b> ---> <b>ChildTable childRef</b> <br/> // ON (parentRef.Col1 = childRef.Col1 AND parentRef.Col2 = childRef.Col2) sb.Append("Relation <br/>"); sb.Append("<b>"); sb.Append(MaskIdentifier(parentBinding.TableBinding.Name)); sb.Append(" AS "); sb.Append(MaskIdentifier(parentBinding.Name)); sb.Append("</b>"); sb.Append(" ---> "); sb.Append("<b>"); sb.Append(MaskIdentifier(childBinding.TableBinding.Name)); sb.Append(" AS "); sb.Append(MaskIdentifier(childBinding.Name)); sb.Append("</b><br/>ON ("); for (int i = 0; i < relation.ColumnCount; i++) { if (i > 0) sb.Append(" AND "); sb.Append(MaskIdentifier(parentBinding.Name)); sb.Append("."); sb.Append(MaskIdentifier(parentColumns[i].Name)); sb.Append(" = "); sb.Append(MaskIdentifier(childBinding.Name)); sb.Append("."); sb.Append(MaskIdentifier(childColumns[i].Name)); } sb.Append(")"); string description = sb.ToString(); sb.Length = 0; // PreText: // ~~~~~~~~ // parentAlias.Col1 = childAlias.Col1 AND parentAlias.Col2 = childAlias.Col2 for (int i = 0; i < relation.ColumnCount; i++) { if (i > 0) sb.Append(" AND "); sb.Append(MaskIdentifier(parentBinding.Name)); sb.Append("."); sb.Append(MaskIdentifier(parentColumns[i].Name)); sb.Append(" = "); sb.Append(MaskIdentifier(childBinding.Name)); sb.Append("."); sb.Append(MaskIdentifier(childColumns[i].Name)); } string preText = sb.ToString(); sb.Length = 0; IntelliPromptMemberListItem item = new IntelliPromptMemberListItem(name, RELATION_IMG_INDEX, description, preText, String.Empty); _members.Add(item); }
private static int GetJoinOrderScore(JoinOrder joinOder, ICollection<ExpressionNode> andParts, TableRefBinding[] tables) { int result = 0; Dictionary<RowBufferEntry, ColumnValueDefinition> introducedColumns = GetIntroducedColumns(joinOder); for (int joinIndex = 0; joinIndex < tables.Length; joinIndex++) { ExpressionNode[] applicableConditions = GetAndPartsApplicableToJoin(introducedColumns, joinOder, joinIndex, andParts, false); result *= 2; result += applicableConditions.Length; if (joinOder.Joins[joinIndex].JoinCondition != null) result += 1; } return result; }
private void Join(TableRefBinding table, JoinCondition joinCondition) { _usedTableList.Add(table); _usedJoinConditionList.Add(joinCondition); if (_usedTableList.Count == _tables.Length) { // We have joined all tables, create the join order. // // First we create a list of the join conditions we used. List<Join> joinList = new List<Join>(); for (int i = 0; i < _usedTableList.Count; i++) { TableRefBinding usedTable = _usedTableList[i]; JoinCondition usedJoinCondition = _usedJoinConditionList[i]; // The first entry will be null, since we do not join from anywhere if (usedJoinCondition != null) { // Since we swapping the join sides according to the direction // we are joining from we need to create a clone. The clone // is a flat copy meaning that the tables and expressions // themselves are not cloned. usedJoinCondition = usedJoinCondition.Clone(); // If the right table is not the table we are joining to // swap the join sides. if (usedJoinCondition.RightTable != usedTable) usedJoinCondition.SwapSides(); } Join join = new Join(); join.JoinCondition = usedJoinCondition; join.TableRefBinding = usedTable; joinList.Add(join); } // Secondly and very important: We also have to create a list of all // join conditions NOT used. Later theses conditions will be combined // with the and-parts since they must also be checked. List<ExpressionNode> unusedConditionList = new List<ExpressionNode>(); foreach (JoinCondition jc in _joinConditions) { if (!_usedJoinConditionList.Contains(jc)) unusedConditionList.Add(jc.ToExpression()); } JoinOrder joinOrder = new JoinOrder(); joinOrder.Joins = joinList.ToArray(); joinOrder.UnusedConditions = unusedConditionList.ToArray(); _joinOrderList.Add(joinOrder); } else { // We are not yet finished with all tables. Find next table // to join with. bool hasJoin = false; foreach (JoinCondition nextJoin in _joinConditions) { if (!_usedJoinConditionList.Contains(nextJoin)) { TableRefBinding nextTable; if (_usedTableList.Contains(nextJoin.LeftTable)) { nextTable = nextJoin.RightTable; } else if (_usedTableList.Contains(nextJoin.RightTable)) { nextTable = nextJoin.LeftTable; } else { continue; } if (_usedTableList.Contains(nextTable)) continue; Join(nextTable, nextJoin); hasJoin = true; } } if (!hasJoin) { foreach (TableRefBinding t in _tables) { if (!_usedTableList.Contains(t)) Join(t, null); } } } _usedJoinConditionList.RemoveAt(_usedJoinConditionList.Count - 1); _usedTableList.RemoveAt(_usedTableList.Count - 1); }
private void AddTable(TableRefBinding table) { if (IsOuterScope(table.Scope) && !_tableBindingList.Contains(table)) _tableBindingList.Add(table); }