public override VisitedExpression Visit(DbPropertyExpression expression) { /* * Algorithm for finding the correct reference expression: "Collection"."Name" * The collection is always a leaf InputExpression, found by lookup in _refToNode. * The name for the collection is found using node.TopName. * * We must now follow the path from the leaf down to the root, * and make sure the column is projected all the way down. * * We need not project columns at a current InputExpression. * For example, in * SELECT ? FROM <from> AS "X" WHERE "X"."field" = <value> * we use the property "field" but it should not be projected. * Current expressions are stored in _currentExpressions. * There can be many of these, for example if we are in a WHERE EXISTS (SELECT ...) or in the right hand side of an Apply expression. * * At join nodes, column names might have to be renamed, if a name collision occurs. * For example, the following would be illegal, * SELECT "X"."A" AS "A", "Y"."A" AS "A" FROM (SELECT 1 AS "A") AS "X" CROSS JOIN (SELECT 1 AS "A") AS "Y" * so we write * SELECT "X"."A" AS "A", "Y"."A" AS "A_Alias<N>" FROM (SELECT 1 AS "A") AS "X" CROSS JOIN (SELECT 1 AS "A") AS "Y" * The new name is then propagated down to the root. */ string name = expression.Property.Name; string from = (expression.Instance.ExpressionKind == DbExpressionKind.Property) ? ((DbPropertyExpression)expression.Instance).Property.Name : ((DbVariableReferenceExpression)expression.Instance).VariableName; PendingProjectsNode node = _refToNode[from]; from = node.TopName; while (node != null) { foreach (var item in node.Selects) { if (_currentExpressions.Contains(item.Exp)) continue; var use = new StringPair(from, name); if (!item.Exp.ColumnsToProject.ContainsKey(use)) { var oldName = name; while (item.Exp.ProjectNewNames.Contains(name)) name = oldName + "_" + NextAlias(); item.Exp.ColumnsToProject[use] = name; item.Exp.ProjectNewNames.Add(name); } else { name = item.Exp.ColumnsToProject[use]; } from = item.AsName; } node = node.JoinParent; } return new ColumnReferenceExpression { Variable = from, Name = name }; }
public override bool Equals(object obj) { if (obj == null) { return(false); } StringPair o = obj as StringPair; if (o == null) { return(false); } return(_item1 == o._item1 && _item2 == o._item2); }
public override VisitedExpression Visit(DbPropertyExpression expression) { /* * Algorithm for finding the correct reference expression: "Collection"."Name" * The collection is always a leaf InputExpression, found by lookup in _refToNode. * The name for the collection is found using node.TopName. * * We must now follow the path from the leaf down to the root, * and make sure the column is projected all the way down. * * We need not project columns at a current InputExpression. * For example, in * SELECT ? FROM <from> AS "X" WHERE "X"."field" = <value> * we use the property "field" but it should not be projected. * Current expressions are stored in _currentExpressions. * There can be many of these, for example if we are in a WHERE EXISTS (SELECT ...) or in the right hand side of an Apply expression. * * At join nodes, column names might have to be renamed, if a name collision occurs. * For example, the following would be illegal, * SELECT "X"."A" AS "A", "Y"."A" AS "A" FROM (SELECT 1 AS "A") AS "X" CROSS JOIN (SELECT 1 AS "A") AS "Y" * so we write * SELECT "X"."A" AS "A", "Y"."A" AS "A_Alias<N>" FROM (SELECT 1 AS "A") AS "X" CROSS JOIN (SELECT 1 AS "A") AS "Y" * The new name is then propagated down to the root. */ string name = expression.Property.Name; string from = (expression.Instance.ExpressionKind == DbExpressionKind.Property) ? ((DbPropertyExpression)expression.Instance).Property.Name : ((DbVariableReferenceExpression)expression.Instance).VariableName; PendingProjectsNode node = _refToNode[from]; from = node.TopName; while (node != null) { foreach (var item in node.Selects) { if (_currentExpressions.Contains(item.Exp)) { continue; } var use = new StringPair(from, name); if (!item.Exp.ColumnsToProject.ContainsKey(use)) { var oldName = name; while (item.Exp.ProjectNewNames.Contains(name)) { name = oldName + "_" + NextAlias(); } item.Exp.ColumnsToProject[use] = name; item.Exp.ProjectNewNames.Add(name); } else { name = item.Exp.ColumnsToProject[use]; } from = item.AsName; } node = node.JoinParent; } return(new ColumnReferenceExpression { Variable = from, Name = name }); }