public override void Visit(WMatchPath node) { foreach (var sourceEdge in node.PathEdgeList) { WSchemaObjectName source = sourceEdge.Item1; string tableAlias = source.BaseIdentifier.Value; WEdgeColumnReferenceExpression edge = sourceEdge.Item2; if (accessedColumns.ContainsKey(tableAlias)) { switch (edge.EdgeType) { case WEdgeType.OutEdge: accessedColumns[tableAlias].Add(ColumnGraphType.OutAdjacencyList.ToString()); break; case WEdgeType.InEdge: accessedColumns[tableAlias].Add(ColumnGraphType.InAdjacencyList.ToString()); break; case WEdgeType.BothEdge: accessedColumns[tableAlias].Add(ColumnGraphType.BothAdjacencyList.ToString()); break; default: break; } } } }
public void AddEdgeReference(string name, WSchemaObjectName sourceNodeName, WEdgeColumnReferenceExpression edgeReference) { if (_nodeTableDictionary.ContainsKey(name) || _edgeDictionary.ContainsKey(name)) { throw new GraphViewException("Duplicate Alias"); } _edgeDictionary.Add(name, new Tuple <WSchemaObjectName, WEdgeColumnReferenceExpression>(sourceNodeName, edgeReference)); }
public WDeleteEdgeSpecification(WSelectQueryBlock deleteSpec) { SelectDeleteExpr = deleteSpec; //FromClause = new WFromClause //{ // TableReferences = new List<WTableReference> // { // new WQueryDerivedTable // { // QueryExpr = deleteSpec // } // } //}; EdgeColumn = deleteSpec.MatchClause.Paths[0].PathEdgeList[0].Item2; }
// Greate the MatchGraph of this AggregationBlock. If some free nodes and free edges are connected, they are in the same ConnectedComponent internal HashSet <string> CreateMatchGraph(WMatchClause matchClause) { HashSet <string> freeNodesAndEdges = new HashSet <string>(); Dictionary <string, MatchPath> pathCollection = new Dictionary <string, MatchPath>(StringComparer.OrdinalIgnoreCase); Dictionary <string, MatchNode> nodeCollection = new Dictionary <string, MatchNode>(StringComparer.OrdinalIgnoreCase); Dictionary <string, MatchEdge> edgeCollection = new Dictionary <string, MatchEdge>(StringComparer.OrdinalIgnoreCase); Dictionary <string, ConnectedComponent> subgraphCollection = new Dictionary <string, ConnectedComponent>(StringComparer.OrdinalIgnoreCase); // we use Disjoint-set data structure to determine whether tables are in the same component or not. UnionFind unionFind = new UnionFind(); foreach (ConnectedComponent subgraph in this.GraphPattern.ConnectedSubgraphs) { foreach (KeyValuePair <string, MatchNode> pair in subgraph.Nodes) { nodeCollection.Add(pair.Key, pair.Value); unionFind.Add(pair.Key); } } if (matchClause != null) { foreach (WMatchPath path in matchClause.Paths) { int index = 0; bool outOfBlock = false; MatchEdge edgeToSrcNode = null; for (int count = path.PathEdgeList.Count; index < count; ++index) { WSchemaObjectName currentNodeTableRef = path.PathEdgeList[index].Item1; WEdgeColumnReferenceExpression currentEdgeColumnRef = path.PathEdgeList[index].Item2; WSchemaObjectName nextNodeTableRef = index != count - 1 ? path.PathEdgeList[index + 1].Item1 : path.Tail; string currentNodeExposedName = currentNodeTableRef.BaseIdentifier.Value; string edgeAlias = currentEdgeColumnRef.Alias; string nextNodeExposedName = nextNodeTableRef != null ? nextNodeTableRef.BaseIdentifier.Value : null; // Get the source node of a path if (!nodeCollection.ContainsKey(currentNodeExposedName)) { continue; } MatchNode srcNode = nodeCollection[currentNodeExposedName]; // Get the edge of a path, and set required attributes // Because the sourceNode is relative, we need to construct new edges or paths // But they need to share the same predicates and proerties MatchEdge edgeFromSrcNode; if (currentEdgeColumnRef.MinLength == 1 && currentEdgeColumnRef.MaxLength == 1) { if (!edgeCollection.ContainsKey(edgeAlias)) { edgeCollection[edgeAlias] = new MatchEdge() { LinkAlias = edgeAlias, SourceNode = srcNode, EdgeType = currentEdgeColumnRef.EdgeType, Predicates = new List <WBooleanExpression>(), BindNodeTableObjName = new WSchemaObjectName(), IsReversed = false, Properties = new List <string>(GraphViewReservedProperties.ReservedEdgeProperties) }; unionFind.Add(edgeAlias); } edgeFromSrcNode = new MatchEdge { LinkAlias = edgeAlias, SourceNode = srcNode, EdgeType = edgeCollection[edgeAlias].EdgeType, Predicates = edgeCollection[edgeAlias].Predicates, BindNodeTableObjName = edgeCollection[edgeAlias].BindNodeTableObjName, IsReversed = false, Properties = edgeCollection[edgeAlias].Properties }; } else { if (!pathCollection.ContainsKey(edgeAlias)) { pathCollection[edgeAlias] = new MatchPath { SourceNode = srcNode, LinkAlias = edgeAlias, Predicates = new List <WBooleanExpression>(), BindNodeTableObjName = new WSchemaObjectName(), MinLength = currentEdgeColumnRef.MinLength, MaxLength = currentEdgeColumnRef.MaxLength, ReferencePathInfo = false, AttributeValueDict = currentEdgeColumnRef.AttributeValueDict, IsReversed = false, EdgeType = currentEdgeColumnRef.EdgeType, Properties = new List <string>(GraphViewReservedProperties.ReservedEdgeProperties) }; } edgeFromSrcNode = new MatchPath { SourceNode = srcNode, LinkAlias = edgeAlias, Predicates = pathCollection[edgeAlias].Predicates, BindNodeTableObjName = pathCollection[edgeAlias].BindNodeTableObjName, MinLength = pathCollection[edgeAlias].MinLength, MaxLength = pathCollection[edgeAlias].MaxLength, ReferencePathInfo = false, AttributeValueDict = pathCollection[edgeAlias].AttributeValueDict, IsReversed = false, EdgeType = pathCollection[edgeAlias].EdgeType, Properties = pathCollection[edgeAlias].Properties }; } if (path.IsReversed) { unionFind.Union(edgeAlias, currentNodeExposedName); } else { unionFind.Union(currentNodeExposedName, edgeAlias); } if (edgeToSrcNode != null) { edgeToSrcNode.SinkNode = srcNode; if (!(edgeToSrcNode is MatchPath)) { // Construct reverse edge MatchEdge reverseEdge = new MatchEdge { SourceNode = edgeToSrcNode.SinkNode, SinkNode = edgeToSrcNode.SourceNode, LinkAlias = edgeToSrcNode.LinkAlias, Predicates = edgeToSrcNode.Predicates, BindNodeTableObjName = edgeToSrcNode.BindNodeTableObjName, IsReversed = true, EdgeType = edgeToSrcNode.EdgeType, Properties = edgeToSrcNode.Properties, }; srcNode.ReverseNeighbors.Add(reverseEdge); } } edgeToSrcNode = edgeFromSrcNode; // Add this edge to node's neightbors if (nextNodeExposedName != null) { if (path.IsReversed) { unionFind.Union(nextNodeExposedName, edgeAlias); } else { unionFind.Union(edgeAlias, nextNodeExposedName); } srcNode.Neighbors.Add(edgeFromSrcNode); } // Add this edge to node's dangling edges else { srcNode.DanglingEdges.Add(edgeFromSrcNode); } } if (path.Tail == null) { continue; } // Get destination node of a path string tailExposedName = path.Tail.BaseIdentifier.Value; if (!nodeCollection.ContainsKey(tailExposedName)) { continue; } MatchNode destNode = nodeCollection[tailExposedName]; if (edgeToSrcNode != null) { edgeToSrcNode.SinkNode = destNode; if (!(edgeToSrcNode is MatchPath)) { // Construct reverse edge MatchEdge reverseEdge = new MatchEdge { SourceNode = edgeToSrcNode.SinkNode, SinkNode = edgeToSrcNode.SourceNode, LinkAlias = edgeToSrcNode.LinkAlias, Predicates = edgeToSrcNode.Predicates, BindNodeTableObjName = edgeToSrcNode.BindNodeTableObjName, IsReversed = true, EdgeType = edgeToSrcNode.EdgeType, Properties = edgeToSrcNode.Properties, }; destNode.ReverseNeighbors.Add(reverseEdge); } } } } // Use union find algorithmn to define which subgraph does a node belong to and put it into where it belongs to. foreach (var node in nodeCollection) { freeNodesAndEdges.Add(node.Key); string root = unionFind.Find(node.Key); ConnectedComponent subGraph; if (!subgraphCollection.ContainsKey(root)) { subGraph = new ConnectedComponent(); subgraphCollection[root] = subGraph; } else { subGraph = subgraphCollection[root]; } subGraph.Nodes[node.Key] = node.Value; subGraph.IsTailNode[node.Value] = false; foreach (MatchEdge edge in node.Value.Neighbors) { subGraph.Edges[edge.LinkAlias] = edge; freeNodesAndEdges.Add(edge.LinkAlias); } foreach (MatchEdge edge in node.Value.DanglingEdges) { subGraph.Edges[edge.LinkAlias] = edge; edge.IsDanglingEdge = true; freeNodesAndEdges.Add(edge.LinkAlias); } if (node.Value.Neighbors.Count + node.Value.ReverseNeighbors.Count + node.Value.DanglingEdges.Count > 0) { node.Value.Properties.Add(GremlinKeyword.Star); } } this.GraphPattern = new MatchGraph(subgraphCollection.Values.ToList()); return(freeNodesAndEdges); }
public virtual void Visit(WEdgeColumnReferenceExpression node) { node.AcceptChildren(this); }
public override void Visit(WEdgeColumnReferenceExpression node) { string nodeStr = string.IsNullOrEmpty(node.Alias) ? node.MultiPartIdentifier.ToString() : $"{node.MultiPartIdentifier} AS {node.Alias}"; this.dfsStack.Push(nodeStr); }
private static bool ParseMatchPathEdge( IList<TSqlParserToken> tokens, ref int nextToken, ref WEdgeColumnReferenceExpression result, ref int farestError) { var currentToken = nextToken; Identifier edgeIdentifier = null; if (!ParseQuotedIdentifier(tokens, ref currentToken, ref edgeIdentifier, ref farestError)) return false; nextToken = currentToken; var spiltEdgeIdentifier = edgeIdentifier.Value.Split(' '); string alias = null; if (spiltEdgeIdentifier.Length > 1) { alias = spiltEdgeIdentifier.Last(); if (GraphViewKeywords._keywords.Contains(alias)) throw new SyntaxErrorException(string.Format("System restricted Name {0} cannot be used", alias)); edgeIdentifier.Value = spiltEdgeIdentifier.First(); } result = new WEdgeColumnReferenceExpression { ColumnType = ColumnType.Regular, MultiPartIdentifier = new WMultiPartIdentifier(edgeIdentifier), FirstTokenIndex = currentToken - 1, LastTokenIndex = currentToken - 1, Alias = alias, AliasRole = AliasType.UserSpecified }; return true; }
private WMatchClause ConstructReversedMatchClause(WSelectQueryBlock node, WSqlTableContext context) { var result = new WMatchClause() { Paths = new List<WMatchPath>(), }; foreach (var path in node.MatchClause.Paths) { var reversedEdgeNameList = new List<string>(); var nodeList = new List<Tuple<WSchemaObjectName, WEdgeColumnReferenceExpression>>(); var edgeList = path.PathEdgeList; for (var i = 0; i < edgeList.Count; ++i) { var sourceTableName = edgeList[i].Item1.Identifiers.Last().Value; var edgeName = edgeList[i].Item2.MultiPartIdentifier.Identifiers.Last().Value; WTableReference sourceTable = context[sourceTableName]; var sourceTableObjectName = (sourceTable as WNamedTableReference).TableObjectName.Identifiers.Last().Value; reversedEdgeNameList.Add(sourceTableObjectName + "_" + edgeName + "Reversed"); } var sinkIdentifier = path.Tail.Identifiers.Last(); for (var i = edgeList.Count - 1; i >= 0; --i) { var nodeName = new WSchemaObjectName() { Identifiers = new List<Identifier> { new Identifier() { Value = sinkIdentifier.Value, QuoteType = sinkIdentifier.QuoteType, } }, }; var originalPath = edgeList[i].Item2; var edgeCol = new WEdgeColumnReferenceExpression() { ColumnType = ColumnType.Regular, Alias = originalPath.Alias, MaxLength = originalPath.MaxLength, MinLength = originalPath.MinLength, AttributeValueDict = originalPath.AttributeValueDict, MultiPartIdentifier = new WMultiPartIdentifier(new Identifier() { QuoteType = originalPath.MultiPartIdentifier.Identifiers.Last().QuoteType, Value = reversedEdgeNameList[i], }), }; nodeList.Add(new Tuple<WSchemaObjectName, WEdgeColumnReferenceExpression>(nodeName, edgeCol)); sinkIdentifier = edgeList[i].Item1.Identifiers.Last(); } result.Paths.Add(new WMatchPath { PathEdgeList = nodeList, Tail = edgeList[0].Item1, IsReversed = true, }); } return result; }
private WMultiCommonTableExpression ConstructDeleteEdgeSelect(WSelectQueryBlock node, WEdgeColumnReferenceExpression edgeCol, string tempTableName ,out WTableReference sinkTable, out WTableReference sourceTable, ref bool hasReversedEdge) { sourceTable = null; sinkTable = null; string sourceTableName = null; string sinkTableName = null; var sourceTableScalar = node.SelectElements[0] as WSelectScalarExpression; if (sourceTableScalar == null) return null; var sourceTableColumn = sourceTableScalar.SelectExpr as WColumnReferenceExpression; if (sourceTableColumn == null) return null; sourceTableName = sourceTableColumn.MultiPartIdentifier.Identifiers.Last().Value; var sourceNodeIdExpr = new WColumnReferenceExpression(); foreach (var identifier in sourceTableColumn.MultiPartIdentifier.Identifiers) sourceNodeIdExpr.Add(identifier); sourceNodeIdExpr.AddIdentifier("GlobalNodeId"); var collectVarVisitor = new CollectVariableVisitor(); var context = collectVarVisitor.Invoke(node); if (!context.NodeTableDictionary.Any()) { throw new GraphViewException("Missing From Clause in Delete Edge statement"); } WColumnReferenceExpression sinkNodeIdExpr = null; sourceTable = context[sourceTableName]; var groupByParams = new List<WScalarExpression>(); for (var index = 1; index < node.SelectElements.Count; ++index) { var element = node.SelectElements[index] as WSelectScalarExpression; if (element == null) return null; //sink table if (index == 1) { var sinkTableColumn = element.SelectExpr as WColumnReferenceExpression; if (sinkTableColumn == null) return null; sinkTableName = sinkTableColumn.MultiPartIdentifier.Identifiers.Last().Value; sinkTable = context[sinkTableName]; sinkNodeIdExpr = new WColumnReferenceExpression(); foreach (var identifier in sinkTableColumn.MultiPartIdentifier.Identifiers) sinkNodeIdExpr.Add(identifier); sinkNodeIdExpr.AddIdentifier("GlobalNodeId"); } } var sourceNodeId = new WSelectScalarExpression { SelectExpr = sourceNodeIdExpr, ColumnName = "src", }; var sinkNodeId = new WSelectScalarExpression { SelectExpr = sinkNodeIdExpr, ColumnName = "sink" }; var edgeId = new WSelectScalarExpression { SelectExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier[] { new Identifier {Value = edgeCol.Alias??string.Format("{0}_{1}_{2}",sourceTableName,edgeCol.MultiPartIdentifier.Identifiers.Last().Value,sinkTableName)}, new Identifier {Value = "Edgeid"} }) }, ColumnName = "edgeid" }; var sourceTableNameRef = sourceTable as WNamedTableReference; if (sourceTableNameRef == null) throw new GraphViewException("Source table of DELETE EDGE statement should be a named table reference."); var sinkTableNameRef = sinkTable as WNamedTableReference; if (sinkTableNameRef == null) throw new GraphViewException("Sink table of DELETE EDGE statement should be a named table reference."); int compare = string.CompareOrdinal(sourceTableNameRef.TableObjectName.ToString(), sinkTableNameRef.TableObjectName.ToString()); using (var command = Tx.Connection.CreateCommand()) { command.Transaction = Tx; command.Parameters.AddWithValue("@schema", WNamedTableReference.SchemaNameToTuple(sourceTableNameRef.TableObjectName).Item1); command.Parameters.AddWithValue("@tableName", sourceTableNameRef.TableObjectName.Identifiers.Last().Value); command.Parameters.AddWithValue("@colName", edgeCol.MultiPartIdentifier.Identifiers.Last().Value); command.Parameters.AddWithValue("@role", WNodeTableColumnRole.Edge); command.CommandText = string.Format(@" SELECT NodeColumn.HasReversedEdge FROM [{0}] AS NodeColumn WHERE NodeColumn.TableSchema = @schema and NodeColumn.TableName = @tableName and NodeColumn.ColumnName = @colName and NodeColumn.ColumnRole = @role", GraphViewConnection.MetadataTables[1]); using (var reader = command.ExecuteReader()) { if (reader.Read()) { hasReversedEdge = bool.Parse(reader[0].ToString()); } } } var reversedEdgeName = sourceTableNameRef.TableObjectName.Identifiers.Last().Value + "_" + edgeCol.MultiPartIdentifier.Identifiers.Last().Value + "Reversed"; var reversedEdgeId = new WSelectScalarExpression { SelectExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier[] { new Identifier {Value = edgeCol.Alias??string.Format("{0}_{1}_{2}",sourceTableName,edgeCol.MultiPartIdentifier.Identifiers.Last().Value,sinkTableName)}, new Identifier {Value = "Edgeid"} }) }, ColumnName = "edgeid" }; var elements = new List<WSelectElement> { sourceNodeId, sinkNodeId, edgeId }; var reversedElements = new List<WSelectElement> { sourceNodeId, sinkNodeId, reversedEdgeId, }; return new WMultiCommonTableExpression { WCommonTableExpressions = new List<WCommonTableExpression>() { new WCommonTableExpression { ExpressionName = new Identifier { Value = hasReversedEdge && compare == 0 ? tempTableName + "_1" : tempTableName }, QueryExpression = new WSelectQueryBlock { FromClause = node.FromClause, WhereClause = new WWhereClause { SearchCondition = node.WhereClause.SearchCondition }, HavingClause = node.HavingClause, OrderByClause = node.OrderByClause, TopRowFilter = node.TopRowFilter, UniqueRowFilter = node.UniqueRowFilter, SelectElements = elements, MatchClause = node.MatchClause, } }, new WCommonTableExpression { ExpressionName = new Identifier { Value = hasReversedEdge && compare == 0 ? tempTableName + "_2" : tempTableName }, QueryExpression = new WSelectQueryBlock { FromClause = node.FromClause, WhereClause = hasReversedEdge ? new WWhereClause { SearchCondition = ObjectExtensions.Copy(node.WhereClause.SearchCondition), } : node.WhereClause, HavingClause = node.HavingClause, OrderByClause = node.OrderByClause, TopRowFilter = node.TopRowFilter, UniqueRowFilter = node.UniqueRowFilter, SelectElements = hasReversedEdge ? reversedElements : elements, MatchClause = hasReversedEdge? ConstructReversedMatchClause(node, context) : node.MatchClause, } }, } }; }
private static bool ParseMatchPathEdge( IList<TSqlParserToken> tokens, ref int nextToken, ref WEdgeColumnReferenceExpression result, ref int farestError) { var currentToken = nextToken; Identifier edgeIdentifier = null; if (!ParseQuotedIdentifier(tokens, ref currentToken, ref edgeIdentifier, ref farestError)) return false; int line = tokens[currentToken].Line; nextToken = currentToken; string alias = null; int maxLen = 1; int minLen = 1; string errorKey = ""; var edgeTokens = LexicalAnalyzer.Tokenize(edgeIdentifier.Value, ref errorKey); if (!string.IsNullOrEmpty(errorKey)) throw new SyntaxErrorException(line, errorKey); int curEdgeToken = 0; int edgeFareastError = 0; string edgeName = null; string strValue = null; Dictionary<string, string> attributeValueDict = null; // Gets edge name if (!ReadToken(edgeTokens, AnnotationTokenType.NameToken, ref curEdgeToken, ref edgeName, ref edgeFareastError)) throw new SyntaxErrorException(line, edgeTokens[edgeFareastError].value); edgeIdentifier.Value = edgeName; // Gets path info if (ReadToken(edgeTokens, "*", ref curEdgeToken, ref strValue, ref edgeFareastError)) { string lengStr = ""; // Gets path minimal length if (ReadToken(edgeTokens, AnnotationTokenType.Integer, ref curEdgeToken, ref lengStr, ref edgeFareastError)) { if (!int.TryParse(lengStr, out minLen) || minLen<0) throw new SyntaxErrorException(line, lengStr, "Min length should be an integer no less than zero"); for (int i = 0; i < 2; i++) { if (!ReadToken(edgeTokens, ".", ref curEdgeToken, ref strValue, ref edgeFareastError)) throw new SyntaxErrorException(line, lengStr, "Two dots should be followed by the minimal length integer"); } // Gets path maximal length if (!ReadToken(edgeTokens, AnnotationTokenType.Integer, ref curEdgeToken, ref lengStr, ref edgeFareastError) || !int.TryParse(lengStr, out maxLen) || maxLen < minLen) throw new SyntaxErrorException(line, lengStr, "Max length should be an integer no less than the min length"); } else { minLen = 0; maxLen = -1; } // Gets edge alias if (ReadToken(edgeTokens, "as", ref curEdgeToken, ref strValue, ref edgeFareastError)) { if (!ReadToken(edgeTokens, AnnotationTokenType.NameToken, ref curEdgeToken, ref alias, ref edgeFareastError)) throw new SyntaxErrorException(line, edgeTokens[edgeFareastError].value); } // Gets predicates on attributes NestedObject jsonNestedObject = null; int braceToken = curEdgeToken; if (ReadToken(edgeTokens, AnnotationTokenType.LeftBrace, ref curEdgeToken, ref strValue, ref edgeFareastError)) { if (!ParseNestedObject(edgeTokens, ref braceToken, ref jsonNestedObject, ref edgeFareastError, true)) throw new SyntaxErrorException(line, "{", "Invalid json string"); else attributeValueDict = (jsonNestedObject as CollectionObject).Collection.ToDictionary(e => e.Key.ToLower(), e => (e.Value is StringObject) ? "'" + ((StringObject) e.Value).Value + "'" : (e.Value as NormalObject).Value); } } // Gets edge alias if (ReadToken(edgeTokens, "as", ref curEdgeToken, ref strValue, ref edgeFareastError)) { if (!ReadToken(edgeTokens, AnnotationTokenType.NameToken, ref curEdgeToken, ref alias, ref edgeFareastError)) throw new SyntaxErrorException(line, edgeTokens[edgeFareastError].value); } result = new WEdgeColumnReferenceExpression { ColumnType = ColumnType.Regular, Alias = alias, LastTokenIndex = currentToken - 1, FirstTokenIndex = currentToken - 1, MaxLength = maxLen, MinLength = minLen, MultiPartIdentifier = new WMultiPartIdentifier(edgeIdentifier), AttributeValueDict = attributeValueDict }; return true; }
private WCommonTableExpression ConstructDeleteEdgeSelect(WSelectQueryBlock node, WEdgeColumnReferenceExpression edgeCol, string tempTableName ,out WTableReference sinkTable, out WTableReference sourceTable) { sourceTable = null; sinkTable = null; string sourceTableName = null; string sinkTableName = null; var sourceTableScalar = node.SelectElements[0] as WSelectScalarExpression; if (sourceTableScalar == null) return null; var sourceTableColumn = sourceTableScalar.SelectExpr as WColumnReferenceExpression; if (sourceTableColumn == null) return null; sourceTableName = sourceTableColumn.MultiPartIdentifier.Identifiers.Last().Value; var sourceNodeIdExpr = new WColumnReferenceExpression(); foreach (var identifier in sourceTableColumn.MultiPartIdentifier.Identifiers) sourceNodeIdExpr.Add(identifier); sourceNodeIdExpr.AddIdentifier("GlobalNodeId"); var collectVarVisitor = new CollectVariableVisitor(); var context = collectVarVisitor.Invoke(node); if (!context.NodeTableDictionary.Any()) { throw new GraphViewException("Missing From Clause in Delete Edge statement"); } WColumnReferenceExpression sinkNodeIdExpr = null; sourceTable = context[sourceTableName]; var groupByParams = new List<WScalarExpression>(); for (var index = 1; index < node.SelectElements.Count; ++index) { var element = node.SelectElements[index] as WSelectScalarExpression; if (element == null) return null; //sink table if (index == 1) { var sinkTableColumn = element.SelectExpr as WColumnReferenceExpression; if (sinkTableColumn == null) return null; sinkTableName = sinkTableColumn.MultiPartIdentifier.Identifiers.Last().Value; sinkTable = context[sinkTableName]; sinkNodeIdExpr = new WColumnReferenceExpression(); foreach (var identifier in sinkTableColumn.MultiPartIdentifier.Identifiers) sinkNodeIdExpr.Add(identifier); sinkNodeIdExpr.AddIdentifier("GlobalNodeId"); } } var sourceNodeId = new WSelectScalarExpression { SelectExpr = sourceNodeIdExpr, ColumnName = "src", }; var sinkNodeId = new WSelectScalarExpression { SelectExpr = sinkNodeIdExpr, ColumnName = "sink" }; var edgeId = new WSelectScalarExpression { SelectExpr = new WColumnReferenceExpression { MultiPartIdentifier = new WMultiPartIdentifier( new Identifier[] { new Identifier {Value = edgeCol.Alias??string.Format("{0}_{1}_{2}",sourceTableName,edgeCol.MultiPartIdentifier.Identifiers.Last().Value,sinkTableName)}, new Identifier {Value = "Edgeid"} } ) }, ColumnName = "edgeid" }; var elements = new List<WSelectElement> { sourceNodeId, sinkNodeId, edgeId }; return new WCommonTableExpression { ExpressionName = new Identifier { Value = tempTableName }, QueryExpression = new WSelectQueryBlock { FromClause = node.FromClause, WhereClause = new WWhereClause { SearchCondition = node.WhereClause.SearchCondition }, HavingClause = node.HavingClause, OrderByClause = node.OrderByClause, TopRowFilter = node.TopRowFilter, UniqueRowFilter = node.UniqueRowFilter, SelectElements = elements, MatchClause = node.MatchClause, } }; }
public void AddEdgeReference(string name, WSchemaObjectName sourceNodeName, WEdgeColumnReferenceExpression edgeReference) { if (_nodeTableDictionary.ContainsKey(name) || _edgeDictionary.ContainsKey(name)) throw new GraphViewException("Duplicate Alias"); _edgeDictionary.Add(name, new Tuple<WSchemaObjectName, WEdgeColumnReferenceExpression>(sourceNodeName, edgeReference)); }