public Dictionary <string, string> GetColumnTableMapping( Dictionary <Tuple <string, string>, Dictionary <string, NodeColumns> > columnsOfNodeTables) { if (_columnTableAliasMapping == null) { _columnTableAliasMapping = new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase); var duplicateColumns = new HashSet <string>(); foreach (var kvp in NodeTableDictionary) { var nodeTable = kvp.Value as WNamedTableReference; if (nodeTable != null) { var nodeTableObjectName = nodeTable.TableObjectName; var nodeTableTuple = WNamedTableReference.SchemaNameToTuple(nodeTableObjectName); foreach ( var property in columnsOfNodeTables[nodeTableTuple].Where(e => e.Value.Role != WNodeTableColumnRole.Edge) .Select(e => e.Key)) { if (!_columnTableAliasMapping.ContainsKey(property.ToLower())) { _columnTableAliasMapping[property.ToLower()] = kvp.Key; } else { duplicateColumns.Add(property.ToLower()); } } } } foreach (var kvp in EdgeDictionary) { var tuple = kvp.Value; var sourceTableObjectName = tuple.Item1; var edgeColumnReference = tuple.Item2; var soureNodeTableTuple = WNamedTableReference.SchemaNameToTuple(sourceTableObjectName); var edgeProperties = columnsOfNodeTables[soureNodeTableTuple][ edgeColumnReference.MultiPartIdentifier.Identifiers.Last().Value.ToLower()]; foreach (var attribute in edgeProperties.ColumnAttributes) { if (!_columnTableAliasMapping.ContainsKey(attribute.ToLower())) { _columnTableAliasMapping[attribute.ToLower()] = kvp.Key; } else { duplicateColumns.Add(attribute.ToLower()); } } } foreach (var col in duplicateColumns) { _columnTableAliasMapping.Remove(col); } } return(_columnTableAliasMapping); }
/// <summary> /// Returns true if there are columns of a specific table referenced in a statement /// </summary> /// <param name="node">The query statement</param> /// <param name="tableName">the table for query</param> /// <param name="context">Sql context with table alias mapping</param> /// <param name="columnsOfNodeTables"></param> /// <param name="conn">A open Sql connection</param> /// <returns></returns> public bool Invoke(WSelectQueryBlock node, string tableName, WSqlTableContext context, Dictionary <Tuple <string, string>, Dictionary <string, NodeColumns> > columnsOfNodeTables) { _tableExists = false; _tableName = tableName; _tableRef = context[tableName] as WNamedTableReference; _columnTableMapping = context.GetColumnTableMapping(columnsOfNodeTables); node.Accept(this); return(_tableExists); }
/// <summary> /// Returns true if there are columns of a specific table referenced in a statement /// </summary> /// <param name="node">The query statement</param> /// <param name="tableName">the table for query</param> /// <param name="context">Sql context with table alias mapping</param> /// <param name="columnsOfNodeTables"></param> /// <param name="conn">A open Sql connection</param> /// <returns></returns> public bool Invoke(WSelectQueryBlock node, string tableName, WSqlTableContext context, Dictionary<Tuple<string, string>, Dictionary<string, NodeColumns>> columnsOfNodeTables) { _tableExists = false; _tableName = tableName; _tableRef = context[tableName] as WNamedTableReference; _columnTableMapping = context.GetColumnToAliasMapping(columnsOfNodeTables); node.Accept(this); return _tableExists; }
public override void Visit(WNamedTableReference node) { if (_nodeTables != null && !_nodeTables.Contains(WNamedTableReference.SchemaNameToTuple(node.TableObjectName))) { //throw new GraphViewException("Invalid Table " + node); return; } var name = node.Alias ?? node.TableObjectName.BaseIdentifier; _results.AddNodeTable(name.Value, node); }
//public virtual WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, GraphMetaData metaData) //{ // var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; // var edgeColIdentifier = edgeIdentifiers.Last(); // var edgeColName = edgeColIdentifier.Value; // HashSet<string> nodeSet; // if (!metaData.NodeViewMapping.TryGetValue( // WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) // nodeSet = null; // NodeColumns columnInfo = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)][ // edgeColIdentifier.Value]; // EdgeInfo edgeInfo = columnInfo.EdgeInfo; // List<Tuple<string, string>> edgeTuples = edgeInfo.EdgeColumns; // var parameters = ConstructEdgeTvfParameters(nodeAlias, "", nodeSet, edgeTuples); // //var isRevEdge = columnInfo.IsReversedEdge; // //string refTableName = null, originalEdgeName = null; // //if (isRevEdge) // //{ // // var index = edgeColName.IndexOf('_'); // // refTableName = edgeColName.Substring(0, index); // // originalEdgeName = edgeColName.Substring(index + 1, // // edgeColName.Length - "Reversed".Length - index - 1); // //} // //var decoderSchemaName = isRevEdge ? columnInfo.RefTableSchema : BindNodeTableObjName.SchemaIdentifier.Value; // //var decoderTableName = isRevEdge ? refTableName : BindNodeTableObjName.BaseIdentifier.Value; // //var decoderEdgeName = isRevEdge ? originalEdgeName : EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value; // //var decoderStr = decoderSchemaName + "_" + decoderTableName + "_" + decoderEdgeName + "_Decoder"; // var decoderFunction = new Identifier // { // Value = edgeInfo.EdgeUdfPrefix + "_Decoder", // }; // return new WSchemaObjectFunctionTableReference // { // SchemaObject = new WSchemaObjectName( // new Identifier { Value = "dbo" }, // decoderFunction), // Parameters = parameters, // Alias = new Identifier // { // Value = EdgeAlias, // } // }; //} /// <summary> /// Converts the edge to the table-valued function /// </summary> /// <param name="nodeAlias">Source node alias</param> /// <param name="dumbNode">Dumb node parameter alias</param> /// <param name="metaData">Meta data</param> /// <returns>A syntax tree node representing the table-valued function</returns> public virtual WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, string dumbNode, GraphMetaData metaData) { var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; var edgeColIdentifier = edgeIdentifiers.Last(); var edgeColName = edgeColIdentifier.Value; var bindNodeTableTuple = WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName); HashSet <string> nodeSet; if (!metaData.NodeViewMapping.TryGetValue( WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) { nodeSet = null; } if (IsEdgeView && IsReversedEdge) { var sinkNodeTableTuple = WNamedTableReference.SchemaNameToTuple(SinkNode.NodeTableObjectName); var index = edgeColName.IndexOf(sinkNodeTableTuple.Item2, StringComparison.OrdinalIgnoreCase); index += sinkNodeTableTuple.Item2.Length; var originalEdgeViewName = edgeColName.Substring(index + 1, edgeColName.Length - "Reversed".Length - index - 1); edgeColName = bindNodeTableTuple.Item2 + "_" + originalEdgeViewName + "Reversed"; } NodeColumns columnInfo = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)][ edgeColName]; EdgeInfo edgeInfo = columnInfo.EdgeInfo; List <Tuple <string, string> > edgeTuples = edgeInfo.EdgeColumns; var parameters = ConstructEdgeTvfParameters(nodeAlias, dumbNode, nodeSet, edgeTuples); var decoderFunction = new Identifier { Value = edgeInfo.EdgeUdfPrefix + "_Decoder", }; return(new WSchemaObjectFunctionTableReference { SchemaObject = new WSchemaObjectName( new Identifier { Value = "dbo" }, decoderFunction), Parameters = parameters, Alias = new Identifier { Value = EdgeAlias, } }); }
public MatchComponent(MatchNode node) : this() { Nodes.Add(node); MaterializedNodeSplitCount[node] = 0; StatisticsDict[node] = new ColumnStatistics { Selectivity = 1.0 / node.TableRowCount }; Size *= node.EstimatedRows; EstimateSize *= node.EstimatedRows; TableRef = new WNamedTableReference { Alias = new Identifier { Value = node.RefAlias }, TableObjectName = node.TableObjectName }; }
public WTableReference ToTableReference(string nodeAlias, GraphMetaData metaData) { // Constructs table reference WTableReference nodeTable = new WNamedTableReference { Alias = new Identifier { Value = nodeAlias }, TableObjectName = TreeRoot.NodeTableObjectName }; nodeTable = MaterializedEdges.Aggregate(nodeTable, (current, edge) => new WUnqualifiedJoin { FirstTableRef = current, SecondTableRef = edge.ToSchemaObjectFunction(nodeAlias, metaData), UnqualifiedJoinType = UnqualifiedJoinType.CrossApply, }); return(nodeTable); }
// We firstly think every node are isolated, and we will find subgraphs later internal string AddTable(WNamedTableReference table) { string alias = table.Alias.Value; this.TableInputDependency[alias] = new HashSet <string>(); MatchNode matchNode = new MatchNode() { NodeAlias = alias, Neighbors = new List <MatchEdge>(), ReverseNeighbors = new List <MatchEdge>(), DanglingEdges = new List <MatchEdge>(), Predicates = new List <WBooleanExpression>(), Properties = new HashSet <string>() }; ConnectedComponent subgraph = new ConnectedComponent(); subgraph.Nodes[alias] = matchNode; this.GraphPattern.ConnectedSubgraphs.Add(subgraph); matchNode.Position = this.TableInputDependency.Count; return(alias); }
/// <summary> /// Converts the edge to the table-valued function /// </summary> /// <param name="nodeAlias">Source node alias</param> /// <param name="metaData">Meta data</param> /// <returns>A syntax tree node representing the table-valued function</returns> public virtual WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, GraphMetaData metaData) { var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; var edgeColIdentifier = edgeIdentifiers.Last(); HashSet <string> nodeSet; if (!metaData.NodeViewMapping.TryGetValue( WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) { nodeSet = null; } EdgeInfo edgeInfo = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)][ edgeColIdentifier.Value].EdgeInfo; List <Tuple <string, string> > edgeTuples = edgeInfo.EdgeColumns; var parameters = ConstructEdgeTvfParameters(nodeAlias, nodeSet, edgeTuples); var decoderFunction = new Identifier { Value = BindNodeTableObjName.SchemaIdentifier.Value + '_' + BindNodeTableObjName.BaseIdentifier.Value + '_' + EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value + '_' + "Decoder" }; return(new WSchemaObjectFunctionTableReference { SchemaObject = new WSchemaObjectName( new Identifier { Value = "dbo" }, decoderFunction), Parameters = parameters, Alias = new Identifier { Value = EdgeAlias, } }); }
public override void Visit(WNamedTableReference node) { vertexTableList.Add(node); }
private WTableReference ParseTableReference(TableReference tabRef) { if (tabRef == null) { return null; } var tabRefWithAlias = tabRef as TableReferenceWithAlias; if (tabRefWithAlias!=null && tabRefWithAlias.Alias!=null && GraphViewKeywords._keywords.Contains(tabRefWithAlias.Alias.Value)) { var token = _tokens[tabRefWithAlias.Alias.FirstTokenIndex]; throw new SyntaxErrorException(token.Line, tabRefWithAlias.Alias.Value, "System restricted Name cannot be used"); } switch (tabRef.GetType().Name) { case "NamedTableReference": { var oref = tabRef as NamedTableReference; if (oref.SchemaObject.BaseIdentifier.QuoteType == QuoteType.NotQuoted && (oref.SchemaObject.BaseIdentifier.Value[0] == '@' || oref.SchemaObject.BaseIdentifier.Value[0] == '#')) { var pref = new WSpecialNamedTableReference { Alias = oref.Alias, TableHints = new List<WTableHint>(), FirstTokenIndex = oref.FirstTokenIndex, LastTokenIndex = oref.LastTokenIndex, TableObjectName = ParseSchemaObjectName(oref.SchemaObject), }; if (oref.TableHints != null) { foreach (var hint in oref.TableHints) pref.TableHints.Add(ParseTableHint(hint)); } return pref; } else { var pref = new WNamedTableReference { Alias = oref.Alias, TableHints = new List<WTableHint>(), FirstTokenIndex = oref.FirstTokenIndex, LastTokenIndex = oref.LastTokenIndex, TableObjectName = ParseSchemaObjectName(oref.SchemaObject), }; if (oref.TableHints != null) { foreach (var hint in oref.TableHints) pref.TableHints.Add(ParseTableHint(hint)); } return pref; } } case "QueryDerivedTable": { var oref = tabRef as QueryDerivedTable; var pref = new WQueryDerivedTable { QueryExpr = ParseSelectQueryStatement(oref.QueryExpression), Alias = oref.Alias, Columns = oref.Columns, FirstTokenIndex = oref.FirstTokenIndex, LastTokenIndex = oref.LastTokenIndex, }; return pref; } case "SchemaObjectFunctionTableReference": { var oref = tabRef as SchemaObjectFunctionTableReference; var pref = new WSchemaObjectFunctionTableReference { Alias = oref.Alias, Columns = oref.Columns, SchemaObject = ParseSchemaObjectName(oref.SchemaObject), FirstTokenIndex = oref.FirstTokenIndex, LastTokenIndex = oref.LastTokenIndex }; if (oref.Parameters == null) return pref; pref.Parameters = new List<WScalarExpression>(); foreach (var param in oref.Parameters) pref.Parameters.Add(ParseScalarExpression(param)); return pref; } case "QualifiedJoin": { var oref = tabRef as QualifiedJoin; var pref = new WQualifiedJoin { FirstTableRef = ParseTableReference(oref.FirstTableReference), SecondTableRef = ParseTableReference(oref.SecondTableReference), QualifiedJoinType = oref.QualifiedJoinType, JoinHint = oref.JoinHint, JoinCondition = ParseBooleanExpression(oref.SearchCondition), FirstTokenIndex = oref.FirstTokenIndex, LastTokenIndex = oref.LastTokenIndex, }; return pref; } case "UnqualifiedJoin": { var oref = tabRef as UnqualifiedJoin; var pref = new WUnqualifiedJoin { FirstTableRef = ParseTableReference(oref.FirstTableReference), SecondTableRef = ParseTableReference(oref.SecondTableReference), UnqualifiedJoinType = oref.UnqualifiedJoinType, FirstTokenIndex = oref.FirstTokenIndex, LastTokenIndex = oref.LastTokenIndex, }; return pref; } case "JoinParenthesisTableReference": { var ptab = tabRef as JoinParenthesisTableReference; var wptab = new WParenthesisTableReference { Table = ParseTableReference(ptab.Join), FirstTokenIndex = ptab.FirstTokenIndex, LastTokenIndex = ptab.LastTokenIndex, }; return wptab; } default: return null; } }
public virtual void Visit(WNamedTableReference node) { node.AcceptChildren(this); }
public override void Visit(WNamedTableReference node) { blocks.Last().AddTable(node); }
public MatchComponent(MatchNode node):this() { Nodes.Add(node); MaterializedNodeSplitCount[node] = 0; StatisticsDict[node] = new ColumnStatistics{Selectivity = 1.0/node.TableRowCount}; Size *= node.EstimatedRows; EstimateSize *= node.EstimatedRows; TableRef = new WNamedTableReference { Alias = new Identifier { Value = node.RefAlias}, TableObjectName = node.TableObjectName }; }
/// <summary> /// Constructs parameters for the edge table-valued function when translation the MATCH clause /// </summary> /// <param name="nodeAlias">Source node alias</param> /// <param name="dumbNode">Dumb node parameter alias</param> /// <param name="nodeTableNameSet">Node table names mapping to the source node of the edge. /// If null, the source node is mapped to a physical table in the syntax tree. Otherewise, /// the source node is mapped to a node view</param> /// <param name="edgeNameTuples">A tuple (Node table name, Edge column name) mapping to the edge. /// If null, the edge is mapped to an edge column in a physical node table. Ohterwise, /// the edge is mapped to an edge view</param> /// <returns>Parameters in the table-valued function</returns> protected List <WScalarExpression> ConstructEdgeTvfParameters(string nodeAlias, string dumbNode, HashSet <string> nodeTableNameSet = null, List <Tuple <string, string> > edgeNameTuples = null) { var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; var edgeColIdentifier = edgeIdentifiers.Last(); Identifier srcNodeIdentifier = new Identifier { Value = nodeAlias }; List <WScalarExpression> parameters = new List <WScalarExpression>(); // The source is a physical node if (nodeTableNameSet == null) { // The edge is a physical edge if (edgeNameTuples == null) { parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, edgeColIdentifier) }); parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, new Identifier { Value = edgeColIdentifier.Value + "DeleteCol" }) }); } // The edge is an edge view else { var sourceTableName = WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName).Item2; foreach (var column in edgeNameTuples) { if (sourceTableName.Equals(column.Item1, StringComparison.OrdinalIgnoreCase)) { Identifier includedEdgeColumnIdentifier = new Identifier { Value = column.Item2 }; parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, includedEdgeColumnIdentifier) }); parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, new Identifier { Value = includedEdgeColumnIdentifier.Value + "DeleteCol" }) }); } else { parameters.Add(new WValueExpression { Value = "null" }); parameters.Add(new WValueExpression { Value = "null" }); } } } } // The source is a node view else { // The edge is a physical edge if (edgeNameTuples == null) { string srcTableName = BindNodeTableObjName.BaseIdentifier.Value; Identifier nodeViewEdgeColIdentifier = new Identifier { Value = srcTableName + "_" + edgeColIdentifier.Value }; parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, nodeViewEdgeColIdentifier) }); parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, new Identifier { Value = nodeViewEdgeColIdentifier.Value + "DeleteCol" }) }); } // The edge is an edge view else { foreach (var column in edgeNameTuples) { if (nodeTableNameSet.Contains(column.Item1)) { Identifier includedEdgeColumnIdentifier = new Identifier { Value = column.Item1 + "_" + column.Item2 }; parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, includedEdgeColumnIdentifier) }); parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(srcNodeIdentifier, new Identifier { Value = includedEdgeColumnIdentifier.Value + "DeleteCol" }) }); } else { parameters.Add(new WValueExpression { Value = "null" }); parameters.Add(new WValueExpression { Value = "null" }); } } } } // dumbNode == NULL -> pathFunction, no dumb alias if (dumbNode != null) { if (string.IsNullOrEmpty(dumbNode)) { parameters.Add(new WValueExpression { Value = "0" }); } else { parameters.Add(new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = dumbNode }, new Identifier { Value = "GlobalNodeId" } ), }); } } return(parameters); }
/// <summary> /// Transit from current component to the new component in the next state given the Node Unit /// </summary> /// <param name="candidateTree"></param> /// <param name="densityDict"></param> /// <param name="subGraph"></param> /// <param name="statisticsCalculator"></param> /// <returns></returns> public MatchComponent GetNextState( OneHeightTree candidateTree, Dictionary<string, double> densityDict, IMatchJoinStatisticsCalculator statisticsCalculator) { var newComponent = new MatchComponent(this); var root = candidateTree.TreeRoot; WBooleanExpression joinCondition = null; string nodeName = ""; // Update Nodes if (newComponent.MaterializedNodeSplitCount.ContainsKey(root)) { newComponent.MaterializedNodeSplitCount[root]++; nodeName = newComponent.GetNodeRefName(root); joinCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = root.RefAlias}, new Identifier {Value = "GlobalNodeId"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ), }, ComparisonType = BooleanComparisonType.Equals }; } else { nodeName = root.RefAlias; newComponent.Nodes.Add(root); newComponent.MaterializedNodeSplitCount[root] = 0; newComponent.StatisticsDict[root] = new ColumnStatistics {Selectivity = 1.0/root.TableRowCount}; } // Constructs table reference WTableReference nodeTable = new WNamedTableReference { Alias = new Identifier { Value = nodeName }, TableObjectName = root.TableObjectName }; WTableReference compTable = newComponent.TableRef; // Updates join conditions double selectivity = 1.0; double degrees = 1.0; var DensityCount = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase); List<MatchEdge> inEdges; if (newComponent.UnmaterializedNodeMapping.TryGetValue(root, out inEdges)) { var firstEdge = inEdges.First(); bool materialized = newComponent.EdgeMaterilizedDict[firstEdge]; newComponent.UnmaterializedNodeMapping.Remove(root); selectivity *= 1.0/root.TableRowCount; // Component materialized edge to root if (materialized) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = firstEdge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ) }, ComparisonType = BooleanComparisonType.Equals }); //var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[root], // new ColumnStatistics {Selectivity = 1.0/root.TableRowCount}); //selectivity *= statistics.Selectivity; //newComponent.StatisticsDict[root] = statistics; if (DensityCount.ContainsKey(root.TableObjectName.ToString())) DensityCount[root.TableObjectName.ToString()]++; else DensityCount[root.TableObjectName.ToString()] = 1; } // Component unmaterialized edge to root else { ColumnStatistics statistics = null; foreach (var edge in inEdges) { // Update component table compTable = SpanTableRef(compTable, edge, newComponent.GetNodeRefName(edge.SourceNode)); newComponent.EdgeMaterilizedDict[edge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = edge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = nodeName}, new Identifier {Value = "GlobalNodeId"} ) }, ComparisonType = BooleanComparisonType.Equals }); statistics = ColumnStatistics.UpdateHistogram(statistics, newComponent.Context.GetEdgeStatistics(edge)); selectivity *= statistics.Selectivity; } newComponent.StatisticsDict[root] = statistics; if (DensityCount.ContainsKey(root.TableObjectName.ToString())) DensityCount[root.TableObjectName.ToString()]+=inEdges.Count; else DensityCount[root.TableObjectName.ToString()] = inEdges.Count; } } var jointEdges = candidateTree.MaterializedEdges; int sinkToSinkCount = 0; foreach (var jointEdge in jointEdges) { // Update node table nodeTable = SpanTableRef(nodeTable, jointEdge, nodeName); degrees *= jointEdge.AverageDegree; newComponent.EdgeMaterilizedDict[jointEdge] = true; var sinkNode = jointEdge.SinkNode; // Leaf to component materialized node if (newComponent.MaterializedNodeSplitCount.ContainsKey(sinkNode)) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = jointEdge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = sinkNode.RefAlias}, new Identifier {Value = "GlobalNodeId"} ) }, ComparisonType = BooleanComparisonType.Equals }); var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode], newComponent.Context.GetEdgeStatistics(jointEdge)); selectivity *= statistics.Selectivity; newComponent.StatisticsDict[sinkNode] = statistics; if (DensityCount.ContainsKey(sinkNode.TableObjectName.ToString())) DensityCount[sinkNode.TableObjectName.ToString()]++; else DensityCount[sinkNode.TableObjectName.ToString()] = 1; } // Leaf to component unmaterialized node else { inEdges = newComponent.UnmaterializedNodeMapping[sinkNode]; var firstEdge = inEdges.First(); bool materlizedEdge = newComponent.EdgeMaterilizedDict[firstEdge]; // Leaf to materialized leaf if (materlizedEdge) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier {Value = jointEdge.EdgeAlias}, new Identifier {Value = "Sink"} ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias}, new Identifier {Value = "Sink"} ) }, ComparisonType = BooleanComparisonType.Equals }); sinkToSinkCount++; var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode], newComponent.Context.GetEdgeStatistics(jointEdge)); selectivity *= statistics.Selectivity; newComponent.StatisticsDict[sinkNode] = statistics; } // Leaf to unmaterialized leaf else { ColumnStatistics compSinkNodeStatistics = null; foreach (var inEdge in inEdges) { compTable = SpanTableRef(compTable, inEdge, newComponent.GetNodeRefName(inEdge.SourceNode)); newComponent.EdgeMaterilizedDict[inEdge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = inEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); sinkToSinkCount++; var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge); selectivity *= leafToLeafStatistics.Selectivity; compSinkNodeStatistics = ColumnStatistics.UpdateHistogram(compSinkNodeStatistics, newComponent.Context.GetEdgeStatistics(inEdge)); } newComponent.StatisticsDict[sinkNode] = compSinkNodeStatistics; } } } var unmatEdges = candidateTree.UnmaterializedEdges; foreach (var unmatEdge in unmatEdges) { newComponent.EdgeMaterilizedDict[unmatEdge] = false; newComponent.Nodes.Add(unmatEdge.SinkNode); var sinkNodeInEdges = newComponent.UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode); sinkNodeInEdges.Add(unmatEdge); degrees *= unmatEdge.AverageDegree; } // Calculate Estimated Join Selectivity & Estimated Node Size double estimatedSelectity = 1.0; int count = 0; bool sinkJoin = false; foreach (var item in densityDict.Where(e => DensityCount.ContainsKey(e.Key))) { var density = item.Value; var curJoinCount = DensityCount[item.Key]; var curJoinSelectitivy = Math.Pow(density, 2 - Math.Pow(2, 1 - curJoinCount)); if (!sinkJoin && ColumnStatistics.DefaultDensity < density) { var curSinkJoinSelectivity = Math.Pow(ColumnStatistics.DefaultDensity, 2 - Math.Pow(2, 1 - sinkToSinkCount)); estimatedSelectity *= Math.Pow(curSinkJoinSelectivity, Math.Pow(2, -count)); count += sinkToSinkCount; sinkJoin = true; } estimatedSelectity *= Math.Pow(curJoinSelectitivy, Math.Pow(2, -count)); count += curJoinCount; } var estimatedNodeUnitSize = root.EstimatedRows* Math.Pow(1000, candidateTree.MaterializedEdges.Count + candidateTree.UnmaterializedEdges.Count); // Update Table Reference newComponent.TableRef = GetPlanAndUpdateCost(candidateTree, newComponent, nodeTable, compTable, joinCondition, degrees, selectivity, estimatedNodeUnitSize, estimatedSelectity); return newComponent; }
/// <summary> /// Converts the edge to the table-valued function /// </summary> /// <param name="nodeAlias">Source node alias</param> /// <param name="dumbNode"></param> /// <param name="metaData">Meta data</param> /// <returns>A syntax tree node representing the table-valued function</returns> public override WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, string dumbNode, GraphMetaData metaData) { var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; var edgeColIdentifier = edgeIdentifiers.Last(); HashSet <string> nodeSet; if (!metaData.NodeViewMapping.TryGetValue( WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) { nodeSet = null; } var sourceNodeColumns = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)]; var edgeInfo = sourceNodeColumns[edgeColIdentifier.Value].EdgeInfo; List <Tuple <string, string> > edgeTuples = edgeInfo.EdgeColumns; var parameters = ConstructEdgeTvfParameters(nodeAlias, null, nodeSet, edgeTuples); Identifier decoderFunction; if (ReferencePathInfo) { decoderFunction = new Identifier { Value = BindNodeTableObjName.SchemaIdentifier.Value + '_' + BindNodeTableObjName.BaseIdentifier.Value + '_' + EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value + '_' + "bfsPathWithMessage" }; // Node view if (nodeSet != null) { parameters.Insert(0, new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier() { Value = SourceNode.RefAlias }, new Identifier() { Value = "_NodeId" }) }); parameters.Insert(0, new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier() { Value = SourceNode.RefAlias }, new Identifier() { Value = "_NodeType" }) }); } else { string nodeIdName = sourceNodeColumns.FirstOrDefault(e => e.Value.Role == WNodeTableColumnRole.NodeId).Key; if (string.IsNullOrEmpty(nodeIdName)) { parameters.Insert(0, new WValueExpression { Value = "null" }); } else { parameters.Insert(0, new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new Identifier() { Value = SourceNode.RefAlias }, new Identifier() { Value = nodeIdName }) }); } parameters.Insert(0, new WValueExpression { Value = BindNodeTableObjName.BaseIdentifier.Value, SingleQuoted = true }); } } else { decoderFunction = new Identifier { Value = BindNodeTableObjName.SchemaIdentifier.Value + '_' + BindNodeTableObjName.BaseIdentifier.Value + '_' + EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value + '_' + "bfsPath" }; } parameters.Insert(0, new WValueExpression { Value = MaxLength.ToString() }); parameters.Insert(0, new WValueExpression { Value = MinLength.ToString() }); parameters.Insert(0, new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier(new[] { new Identifier { Value = nodeAlias }, new Identifier { Value = "GlobalNodeId" }, }) }); var attributes = edgeInfo.ColumnAttributes; if (AttributeValueDict == null) { WValueExpression nullExpression = new WValueExpression { Value = "null" }; for (int i = 0; i < attributes.Count; i++) { parameters.Add(nullExpression); } } else { foreach (var attribute in attributes) { string value; var valueExpression = new WValueExpression { Value = AttributeValueDict.TryGetValue(attribute, out value) ? value : "null" }; parameters.Add(valueExpression); } } return(new WSchemaObjectFunctionTableReference { SchemaObject = new WSchemaObjectName( new Identifier { Value = "dbo" }, decoderFunction), Parameters = parameters, Alias = new Identifier { Value = EdgeAlias, } }); }
public WTableReference ToTableReference(string nodeAlias,GraphMetaData metaData) { // Constructs table reference WTableReference nodeTable = new WNamedTableReference { Alias = new Identifier { Value = nodeAlias }, TableObjectName = TreeRoot.NodeTableObjectName }; nodeTable = MaterializedEdges.Aggregate(nodeTable, (current, edge) => new WUnqualifiedJoin { FirstTableRef = current, SecondTableRef = edge.ToSchemaObjectFunction(nodeAlias, metaData), UnqualifiedJoinType = UnqualifiedJoinType.CrossApply, }); return nodeTable; }
/// <summary> /// Transit from current component to the new component in the next state given the Node Unit /// </summary> /// <param name="candidateTree"></param> /// <param name="densityDict"></param> /// <param name="subGraph"></param> /// <param name="statisticsCalculator"></param> /// <returns></returns> public MatchComponent GetNextState( OneHeightTree candidateTree, Dictionary <string, double> densityDict, IMatchJoinStatisticsCalculator statisticsCalculator) { var newComponent = new MatchComponent(this); var root = candidateTree.TreeRoot; WBooleanExpression joinCondition = null; string nodeName = ""; // Update Nodes if (newComponent.MaterializedNodeSplitCount.ContainsKey(root)) { newComponent.MaterializedNodeSplitCount[root]++; nodeName = newComponent.GetNodeRefName(root); joinCondition = new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = root.RefAlias }, new Identifier { Value = "GlobalNodeId" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ), }, ComparisonType = BooleanComparisonType.Equals }; } else { nodeName = root.RefAlias; newComponent.Nodes.Add(root); newComponent.MaterializedNodeSplitCount[root] = 0; newComponent.StatisticsDict[root] = new ColumnStatistics { Selectivity = 1.0 / root.TableRowCount }; } // Constructs table reference WTableReference nodeTable = new WNamedTableReference { Alias = new Identifier { Value = nodeName }, TableObjectName = root.TableObjectName }; WTableReference compTable = newComponent.TableRef; // Updates join conditions double selectivity = 1.0; double degrees = 1.0; var DensityCount = new Dictionary <string, int>(StringComparer.CurrentCultureIgnoreCase); List <MatchEdge> inEdges; if (newComponent.UnmaterializedNodeMapping.TryGetValue(root, out inEdges)) { var firstEdge = inEdges.First(); bool materialized = newComponent.EdgeMaterilizedDict[firstEdge]; newComponent.UnmaterializedNodeMapping.Remove(root); selectivity *= 1.0 / root.TableRowCount; // Component materialized edge to root if (materialized) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); //var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[root], // new ColumnStatistics {Selectivity = 1.0/root.TableRowCount}); //selectivity *= statistics.Selectivity; //newComponent.StatisticsDict[root] = statistics; if (DensityCount.ContainsKey(root.TableObjectName.ToString())) { DensityCount[root.TableObjectName.ToString()]++; } else { DensityCount[root.TableObjectName.ToString()] = 1; } } // Component unmaterialized edge to root else { ColumnStatistics statistics = null; foreach (var edge in inEdges) { // Update component table compTable = SpanTableRef(compTable, edge, newComponent.GetNodeRefName(edge.SourceNode)); newComponent.EdgeMaterilizedDict[edge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = edge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = nodeName }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); statistics = ColumnStatistics.UpdateHistogram(statistics, newComponent.Context.GetEdgeStatistics(edge)); selectivity *= statistics.Selectivity; } newComponent.StatisticsDict[root] = statistics; if (DensityCount.ContainsKey(root.TableObjectName.ToString())) { DensityCount[root.TableObjectName.ToString()] += inEdges.Count; } else { DensityCount[root.TableObjectName.ToString()] = inEdges.Count; } } } var jointEdges = candidateTree.MaterializedEdges; int sinkToSinkCount = 0; foreach (var jointEdge in jointEdges) { // Update node table nodeTable = SpanTableRef(nodeTable, jointEdge, nodeName); degrees *= jointEdge.AverageDegree; newComponent.EdgeMaterilizedDict[jointEdge] = true; var sinkNode = jointEdge.SinkNode; // Leaf to component materialized node if (newComponent.MaterializedNodeSplitCount.ContainsKey(sinkNode)) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = sinkNode.RefAlias }, new Identifier { Value = "GlobalNodeId" } ) }, ComparisonType = BooleanComparisonType.Equals }); var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode], newComponent.Context.GetEdgeStatistics(jointEdge)); selectivity *= statistics.Selectivity; newComponent.StatisticsDict[sinkNode] = statistics; if (DensityCount.ContainsKey(sinkNode.TableObjectName.ToString())) { DensityCount[sinkNode.TableObjectName.ToString()]++; } else { DensityCount[sinkNode.TableObjectName.ToString()] = 1; } } // Leaf to component unmaterialized node else { inEdges = newComponent.UnmaterializedNodeMapping[sinkNode]; var firstEdge = inEdges.First(); bool materlizedEdge = newComponent.EdgeMaterilizedDict[firstEdge]; // Leaf to materialized leaf if (materlizedEdge) { joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = firstEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); sinkToSinkCount++; var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode], newComponent.Context.GetEdgeStatistics(jointEdge)); selectivity *= statistics.Selectivity; newComponent.StatisticsDict[sinkNode] = statistics; } // Leaf to unmaterialized leaf else { ColumnStatistics compSinkNodeStatistics = null; foreach (var inEdge in inEdges) { compTable = SpanTableRef(compTable, inEdge, newComponent.GetNodeRefName(inEdge.SourceNode)); newComponent.EdgeMaterilizedDict[inEdge] = true; joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression { FirstExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = jointEdge.EdgeAlias }, new Identifier { Value = "Sink" } ), }, SecondExpr = new WColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier( new Identifier { Value = inEdge.EdgeAlias }, new Identifier { Value = "Sink" } ) }, ComparisonType = BooleanComparisonType.Equals }); sinkToSinkCount++; var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge); selectivity *= leafToLeafStatistics.Selectivity; compSinkNodeStatistics = ColumnStatistics.UpdateHistogram(compSinkNodeStatistics, newComponent.Context.GetEdgeStatistics(inEdge)); } newComponent.StatisticsDict[sinkNode] = compSinkNodeStatistics; } } } var unmatEdges = candidateTree.UnmaterializedEdges; foreach (var unmatEdge in unmatEdges) { newComponent.EdgeMaterilizedDict[unmatEdge] = false; newComponent.Nodes.Add(unmatEdge.SinkNode); var sinkNodeInEdges = newComponent.UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode); sinkNodeInEdges.Add(unmatEdge); degrees *= unmatEdge.AverageDegree; } // Calculate Estimated Join Selectivity & Estimated Node Size double estimatedSelectity = 1.0; int count = 0; bool sinkJoin = false; foreach (var item in densityDict.Where(e => DensityCount.ContainsKey(e.Key))) { var density = item.Value; var curJoinCount = DensityCount[item.Key]; var curJoinSelectitivy = Math.Pow(density, 2 - Math.Pow(2, 1 - curJoinCount)); if (!sinkJoin && ColumnStatistics.DefaultDensity < density) { var curSinkJoinSelectivity = Math.Pow(ColumnStatistics.DefaultDensity, 2 - Math.Pow(2, 1 - sinkToSinkCount)); estimatedSelectity *= Math.Pow(curSinkJoinSelectivity, Math.Pow(2, -count)); count += sinkToSinkCount; sinkJoin = true; } estimatedSelectity *= Math.Pow(curJoinSelectitivy, Math.Pow(2, -count)); count += curJoinCount; } var estimatedNodeUnitSize = root.EstimatedRows * Math.Pow(1000, candidateTree.MaterializedEdges.Count + candidateTree.UnmaterializedEdges.Count); // Update Table Reference newComponent.TableRef = GetPlanAndUpdateCost(candidateTree, newComponent, nodeTable, compTable, joinCondition, degrees, selectivity, estimatedNodeUnitSize, estimatedSelectity); return(newComponent); }
//private double _edgeDegrees = -1; //public double EdgeDegrees //{ // get // { // if (_edgeDegrees < 0) // { // double matEdgeDegrees = MaterializedEdges.Aggregate(1.0, (cur, next) => cur*next.AverageDegree); // double unMatEdgeDegrees = UnmaterializedEdges.Aggregate(1.0, (cur, next) => cur * next.AverageDegree); // _edgeDegrees = unMatEdgeDegrees*matEdgeDegrees; // } // return _edgeDegrees; // } //} //private double _sqlEstimatedEdgeDegrees = -1; //public double SqlEstimatedEdgeDegrees //{ // get // { // if (_sqlEstimatedEdgeDegrees < 0) // { // _sqlEstimatedEdgeDegrees = Math.Pow(1000, MaterializedEdges.Count + UnmaterializedEdges.Count); // } // return _sqlEstimatedEdgeDegrees; // } //} //public WTableReference ToTableReference(string nodeAlias, GraphMetaData metaData) //{ // // Constructs table reference // WTableReference nodeTable = new WNamedTableReference // { // Alias = new Identifier { Value = nodeAlias }, // TableObjectName = TreeRoot.NodeTableObjectName // }; // nodeTable = MaterializedEdges.Aggregate(nodeTable, (current, edge) => new WUnqualifiedJoin // { // FirstTableRef = current, // SecondTableRef = edge.ToSchemaObjectFunction(nodeAlias, metaData), // UnqualifiedJoinType = UnqualifiedJoinType.CrossApply, // }); // return nodeTable; //} public WTableReference ToTableReference(string nodeAlias, string dumbNode, GraphMetaData metaData) { // Constructs table reference WTableReference nodeTable = new WNamedTableReference { Alias = new Identifier { Value = nodeAlias }, TableObjectName = TreeRoot.NodeTableObjectName }; if (PreMatOutgoingEdges != null && PreMatOutgoingEdges.Any()) { nodeTable = PreMatOutgoingEdges.Aggregate(nodeTable, (current, edge) => new WUnqualifiedJoin { FirstTableRef = current, SecondTableRef = edge.ToSchemaObjectFunction(nodeAlias, dumbNode, metaData), UnqualifiedJoinType = UnqualifiedJoinType.CrossApply, }); } return nodeTable; }
public MatchComponent(MatchNode node) : this() { Nodes.Add(node); MaterializedNodeSplitCount[node] = 0; //SinkNodeStatisticsDict[node] = new Statistics (); Cardinality *= node.EstimatedRows; SqlEstimatedSize *= node.EstimatedRows; TableRef = new WNamedTableReference { Alias = new Identifier { Value = node.RefAlias}, TableObjectName = node.NodeTableObjectName }; LastTableAlias = node.RefAlias; LastTable = null; foreach (var edge in node.Neighbors) { var edgeList = UnmaterializedNodeMapping.GetOrCreate(edge.SinkNode); edgeList.Add(edge); } }