internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewCommand command) { var dropTargetParameter = Parameters[0] as WColumnReferenceExpression; var dropTargetIndex = context.LocateColumnReference(dropTargetParameter); List <string> populateColumns = new List <string>() { GremlinKeyword.TableDefaultColumnName }; for (int i = 1; i < this.Parameters.Count; i++) { WValueExpression populateColumn = this.Parameters[i] as WValueExpression; Debug.Assert(populateColumn != null, "populateColumn != null"); populateColumns.Add(populateColumn.Value); } var dropOp = new DropOperator(context.CurrentExecutionOperator, command, dropTargetIndex); context.CurrentExecutionOperator = dropOp; foreach (string columnName in populateColumns) { context.AddField(Alias.Value, columnName, ColumnGraphType.Value); } return(dropOp); }
internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewConnection dbConnection) { WScalarSubquery srcSubQuery = this.Parameters[0] as WScalarSubquery; WScalarSubquery sinkSubQuery = this.Parameters[1] as WScalarSubquery; if (srcSubQuery == null || sinkSubQuery == null) { throw new SyntaxErrorException("The first two parameters of AddE can only be WScalarSubquery."); } WValueExpression otherVTagParameter = this.Parameters[2] as WValueExpression; WValueExpression edgeLabel = this.Parameters[3] as WValueExpression; Debug.Assert(otherVTagParameter != null, "otherVTagParameter != null"); // // if otherVTag == 0, this newly added edge's otherV() is the src vertex. // Otherwise, it's the sink vertex // int otherVTag = int.Parse(otherVTagParameter.Value); List <WPropertyExpression> edgeProperties = new List <WPropertyExpression>(); List <string> projectedField = new List <string>(); for (int i = 4; i < this.Parameters.Count; i += 1) { WPropertyExpression addedProperty = this.Parameters[i] as WPropertyExpression; if (addedProperty != null) { edgeProperties.Add(addedProperty); } WValueExpression projectedProperty = this.Parameters[i] as WValueExpression; if (projectedProperty != null) { projectedField.Add(projectedProperty.Value); } } JObject edgeJsonObject = this.ConstructEdgeJsonObject(edgeLabel, edgeProperties); QueryCompilationContext srcSubContext = new QueryCompilationContext(context); GraphViewExecutionOperator srcSubQueryOp = srcSubQuery.SubQueryExpr.Compile(srcSubContext, dbConnection); QueryCompilationContext sinkSubContext = new QueryCompilationContext(context); GraphViewExecutionOperator sinkSubQueryOp = sinkSubQuery.SubQueryExpr.Compile(sinkSubContext, dbConnection); GraphViewExecutionOperator addEOp = new AddEOperator(context.CurrentExecutionOperator, dbConnection, srcSubContext.OuterContextOp, srcSubQueryOp, sinkSubContext.OuterContextOp, sinkSubQueryOp, otherVTag, edgeJsonObject, projectedField); context.CurrentExecutionOperator = addEOp; foreach (string propertyName in projectedField) { ColumnGraphType columnGraphType = GraphViewReservedProperties.IsEdgeReservedProperty(propertyName) ? GraphViewReservedProperties.ReservedEdgePropertiesColumnGraphTypes[propertyName] : ColumnGraphType.Value; context.AddField(this.Alias.Value, propertyName, columnGraphType); } return(addEOp); }
public static JValue ToJValue(this WValueExpression expr) { // // Special treat when fieldValue indicates null (that is, to remove a property) // NOTE: fieldValue itself != null // if (!expr.SingleQuoted && expr.Value.Equals("null", StringComparison.OrdinalIgnoreCase)) { return(null); } // // JSON requires a lower case string if it is a boolean value // bool boolValue; if (!expr.SingleQuoted && bool.TryParse(expr.Value, out boolValue)) { return((JValue)boolValue); } else if (expr.SingleQuoted) { return((JValue)expr.Value); // String value } else { return((JValue)JToken.Parse(expr.ToString())); } }
public static JProperty UpdateProperty(JObject jsonObject, WValueExpression fieldName, WValueExpression fieldValue) { string key = fieldName.Value; // // Special treat when fieldValue indicates null (that is, to remove a property) // NOTE: fieldValue itself != null // if (!fieldValue.SingleQuoted && fieldValue.Value.Equals("null", StringComparison.OrdinalIgnoreCase)) { jsonObject.Property(key)?.Remove(); return(null); } // // JSON requires a lower case string if it is a boolean value // bool boolValue; if (!fieldValue.SingleQuoted && bool.TryParse(fieldValue.Value, out boolValue)) { jsonObject[key] = (JToken)boolValue; } else { jsonObject[key] = JToken.Parse(fieldValue.ToString()); } return(jsonObject.Property(key)); }
public override void Visit(WValueExpression valueExpression) { bool bool_value; // JSON requires a lower case string if it is a boolean value if (!valueExpression.SingleQuoted && bool.TryParse(valueExpression.Value, out bool_value)) { valueExpression.Value = bool_value.ToString().ToLowerInvariant(); } }
internal static void GetPathStepListAndByFuncList( QueryCompilationContext context, GraphViewCommand command, IList <WScalarExpression> parameters, out List <Tuple <ScalarFunction, bool, HashSet <string> > > pathStepList, out List <ScalarFunction> byFuncList) { // // If the boolean value is true, then it's a subPath to be unfolded // pathStepList = new List <Tuple <ScalarFunction, bool, HashSet <string> > >(); byFuncList = new List <ScalarFunction>(); QueryCompilationContext byInitContext = new QueryCompilationContext(context); byInitContext.ClearField(); byInitContext.AddField(GremlinKeyword.Compose1TableDefaultName, GremlinKeyword.TableDefaultColumnName, ColumnGraphType.Value); foreach (WScalarExpression expression in parameters) { WFunctionCall basicStep = expression as WFunctionCall; WValueExpression stepLabel = expression as WValueExpression; WColumnReferenceExpression subPath = expression as WColumnReferenceExpression; WScalarSubquery byFunc = expression as WScalarSubquery; if (basicStep != null) { pathStepList.Add( new Tuple <ScalarFunction, bool, HashSet <string> >( basicStep.CompileToFunction(context, command), false, new HashSet <string>())); } else if (stepLabel != null) { if (!pathStepList.Any()) { pathStepList.Add(new Tuple <ScalarFunction, bool, HashSet <string> >(null, false, new HashSet <string>())); } pathStepList.Last().Item3.Add(stepLabel.Value); } else if (subPath != null) { pathStepList.Add( new Tuple <ScalarFunction, bool, HashSet <string> >( subPath.CompileToFunction(context, command), true, new HashSet <string>())); } else if (byFunc != null) { byFuncList.Add(byFunc.CompileToFunction(byInitContext, command)); } else { throw new QueryCompilationException( "The parameter of WPathTableReference can only be a WFunctionCall/WValueExpression/WColumnReferenceExpression/WScalarSubquery."); } } }
public override void Visit(WValueExpression node) { string value = node.ToString(""); // TODO: double check, how to use boolean type in database? // if (value == "true" || value == "false") // { // value = $"'{value}'"; // } this.dfsStack.Push(value); }
public JObject ConstructNodeJsonDocument(string vertexLabel, List <WPropertyExpression> vertexProperties, out List <string> projectedFieldList) { Debug.Assert(vertexLabel != null); JObject vertexObject = new JObject { ["label"] = vertexLabel }; projectedFieldList = new List <string>(GraphViewReservedProperties.ReservedNodeProperties); foreach (WPropertyExpression vertexProperty in vertexProperties) { Debug.Assert(vertexProperty.Cardinality == GremlinKeyword.PropertyCardinality.list); if (!projectedFieldList.Contains(vertexProperty.Key.Value)) { projectedFieldList.Add(vertexProperty.Key.Value); } if (vertexProperty.Value.ToJValue() == null) { continue; } JObject meta = new JObject(); foreach (KeyValuePair <WValueExpression, WValueExpression> pair in vertexProperty.MetaProperties) { WValueExpression metaName = pair.Key; WValueExpression metaValue = pair.Value; meta[metaName.Value] = metaValue.ToJValue(); } string name = vertexProperty.Key.Value; JArray propArray = (JArray)vertexObject[name]; if (propArray == null) { propArray = new JArray(); vertexObject[name] = propArray; } propArray.Add(new JObject { ["_value"] = vertexProperty.Value.ToJValue(), ["_propId"] = GraphViewConnection.GenerateDocumentId(), ["_meta"] = meta, }); //GraphViewJsonCommand.AppendVertexSinglePropertyToVertex(vertexObject); } vertexObject["_edge"] = new JArray(); vertexObject["_reverse_edge"] = new JArray(); vertexObject["_nextEdgeOffset"] = 0; return(vertexObject); }
public JObject ConstructNodeJsonDocument(string vertexLabel, List <WPropertyExpression> vertexProperties) { Debug.Assert(vertexLabel != null); JObject vertexObject = new JObject { [KW_VERTEX_LABEL] = vertexLabel }; //projectedFieldList = new List<string>(GraphViewReservedProperties.InitialPopulateNodeProperties); //projectedFieldList.Add(GremlinKeyword.Label); foreach (WPropertyExpression vertexProperty in vertexProperties) { Debug.Assert(vertexProperty.Cardinality == GremlinKeyword.PropertyCardinality.List); //if (!projectedFieldList.Contains(vertexProperty.Key.Value)) // projectedFieldList.Add(vertexProperty.Key.Value); //if (vertexProperty.Value.ToJValue() == null) { // continue; //} JObject meta = new JObject(); foreach (KeyValuePair <WValueExpression, WValueExpression> pair in vertexProperty.MetaProperties) { WValueExpression metaName = pair.Key; WValueExpression metaValue = pair.Value; meta[metaName.Value] = metaValue.ToJValue(); } string name = vertexProperty.Key.Value; JArray propArray = (JArray)vertexObject[name]; if (propArray == null) { propArray = new JArray(); vertexObject[name] = propArray; } propArray.Add(new JObject { [KW_PROPERTY_VALUE] = vertexProperty.Value.ToJValue(), [KW_PROPERTY_ID] = GraphViewConnection.GenerateDocumentId(), [KW_PROPERTY_META] = meta, }); //GraphViewJsonCommand.AppendVertexSinglePropertyToVertex(vertexObject); } vertexObject[KW_VERTEX_EDGE] = new JArray(); vertexObject[KW_VERTEX_REV_EDGE] = new JArray(); vertexObject[KW_VERTEX_EDGE_SPILLED] = false; vertexObject[KW_VERTEX_REVEDGE_SPILLED] = false; //vertexObject[KW_VERTEX_NEXTOFFSET] = 0; return(vertexObject); }
public JObject ConstructEdgeJsonObject(WValueExpression edgeLabel, List <WPropertyExpression> addedProperties) { JObject edgeJsonDocument = new JObject(); GraphViewJsonCommand.UpdateProperty(edgeJsonDocument, SqlUtil.GetValueExpr(GremlinKeyword.Label), edgeLabel); foreach (WPropertyExpression property in addedProperties) { GraphViewJsonCommand.UpdateProperty(edgeJsonDocument, property.Key, property.Value); } return(edgeJsonDocument); }
private void UpdateNodeProperties( Dictionary <string, JObject> documentsMap, string vertexId, JObject vertexDocObject, List <Tuple <WValueExpression, WValueExpression, int> > propList, UpdatePropertyMode mode) { VertexField vertexField = this.Connection.VertexCache.GetVertexField(vertexId); // Drop all non-reserved properties if (propList.Count == 1 && !propList[0].Item1.SingleQuoted && propList[0].Item1.Value.Equals("*", StringComparison.OrdinalIgnoreCase) && !propList[0].Item2.SingleQuoted && propList[0].Item2.Value.Equals("null", StringComparison.OrdinalIgnoreCase)) { List <string> toBeDroppedPropertiesNames = GraphViewJsonCommand.DropAllNodeProperties(vertexDocObject); foreach (var propertyName in toBeDroppedPropertiesNames) { vertexField.VertexProperties.Remove(propertyName); } } else { foreach (var t in propList) { WValueExpression keyExpression = t.Item1; WValueExpression valueExpression = t.Item2; if (mode == UpdatePropertyMode.Set) { JProperty updatedProperty = GraphViewJsonCommand.UpdateProperty(vertexDocObject, keyExpression, valueExpression); if (updatedProperty == null) { vertexField.VertexProperties.Remove(keyExpression.Value); } else { vertexField.UpdateVertexProperty(updatedProperty.Name, updatedProperty.Value.ToString(), JsonDataTypeHelper.GetJsonDataType(updatedProperty.Value.Type)); } } else { throw new NotImplementedException(); } } } documentsMap[vertexId] = vertexDocObject; }
internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewConnection dbConnection) { // // Parameters: // #1 <WValueExpression>: Vertex label // ... <WPropertyExpression>: The initial properties on vertex // ... <WValueExpression>: The projected field of AddV WValueExpression labelValue = (WValueExpression)this.Parameters[0]; List <WPropertyExpression> vertexProperties = new List <WPropertyExpression>(); List <string> projectedField = new List <string>(); for (int i = 1; i < this.Parameters.Count; i++) { WPropertyExpression addedProperty = this.Parameters[i] as WPropertyExpression; if (addedProperty != null) { vertexProperties.Add(addedProperty); } WValueExpression projectedProperty = this.Parameters[i] as WValueExpression; if (projectedProperty != null) { projectedField.Add(projectedProperty.Value); } //Debug.Assert(property != null, "[WAddVTableReference.Compile] Vertex property should not be null"); //Debug.Assert(property.Cardinality == GremlinKeyword.PropertyCardinality.List, "[WAddVTableReference.Compile] Vertex property should be append-mode"); //Debug.Assert(property.Value != null); } JObject nodeJsonDocument = this.ConstructNodeJsonDocument(labelValue.Value, vertexProperties); AddVOperator addVOp = new AddVOperator( context.CurrentExecutionOperator, dbConnection, nodeJsonDocument, projectedField); context.CurrentExecutionOperator = addVOp; foreach (string propertyName in projectedField) { ColumnGraphType columnGraphType = GraphViewReservedProperties.IsNodeReservedProperty(propertyName) ? GraphViewReservedProperties.ReservedNodePropertiesColumnGraphTypes[propertyName] : ColumnGraphType.Value; context.AddField(this.Alias.Value, propertyName, columnGraphType); } return(addVOp); }
/// <summary> /// </summary> /// <param name="command"></param> /// <param name="edgeLabel"></param> /// <param name="edgeProperties">All propertyValue is WValueExpression!</param> /// <returns></returns> public JObject ConstructEdgeJsonObject(GraphViewCommand command, string edgeLabel, List <WPropertyExpression> edgeProperties) { JObject edgeObject = new JObject { [KW_EDGE_LABEL] = edgeLabel }; // Skip edgeSourceScalarFunction, edgeSinkScalarFunction, otherVTag foreach (WPropertyExpression edgeProperty in edgeProperties) { WValueExpression propertyValue = edgeProperty.Value as WValueExpression; GraphViewJsonCommand.UpdateProperty(edgeObject, edgeProperty.Key, propertyValue); } return(edgeObject); }
internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewConnection dbConnection) { // // Parameters: // #1 <WValueExpression>: Vertex label // ... <WPropertyExpression>: The initial properties on vertex // WValueExpression labelValue = (WValueExpression)this.Parameters[0]; List <WPropertyExpression> vertexProperties = new List <WPropertyExpression>(); for (int i = 1; i < this.Parameters.Count; i++) { WPropertyExpression property = (WPropertyExpression)this.Parameters[i]; Debug.Assert(property != null, "[WAddVTableReference.Compile] Vertex property should not be null"); Debug.Assert(property.Cardinality == GremlinKeyword.PropertyCardinality.list, "[WAddVTableReference.Compile] Vertex property should be append-mode"); Debug.Assert(property.Value != null); vertexProperties.Add(property); } List <string> projectedField; JObject nodeJsonDocument = ConstructNodeJsonDocument(labelValue.Value, vertexProperties, out projectedField); AddVOperator addVOp = new AddVOperator( context.CurrentExecutionOperator, dbConnection, nodeJsonDocument, projectedField); context.CurrentExecutionOperator = addVOp; context.AddField(Alias.Value, "id", ColumnGraphType.VertexId); context.AddField(Alias.Value, "label", ColumnGraphType.Value); context.AddField(Alias.Value, "_edge", ColumnGraphType.OutAdjacencyList); context.AddField(Alias.Value, "_reverse_edge", ColumnGraphType.InAdjacencyList); context.AddField(Alias.Value, "*", ColumnGraphType.VertexObject); for (var i = GraphViewReservedProperties.ReservedNodeProperties.Count; i < projectedField.Count; i++) { context.AddField(Alias.Value, projectedField[i], ColumnGraphType.Value); } return(addVOp); }
public static JValue ToJValue(this WValueExpression expr) { // // JSON requires a lower case string if it is a boolean value // bool boolValue; if (!expr.SingleQuoted && bool.TryParse(expr.Value, out boolValue)) { return((JValue)boolValue); } else if (expr.SingleQuoted) { return((JValue)expr.Value); // String value } else { return((JValue)JToken.Parse(expr.ToString())); } }
private WScalarExpression ParseScalarExpression(ScalarExpression scalarExpr) { if (scalarExpr == null) { return null; } switch (scalarExpr.GetType().Name) { case "BinaryExpression": { var bexpr = scalarExpr as BinaryExpression; var wexpr = new WBinaryExpression { ExpressionType = bexpr.BinaryExpressionType, FirstExpr = ParseScalarExpression(bexpr.FirstExpression), SecondExpr = ParseScalarExpression(bexpr.SecondExpression), FirstTokenIndex = bexpr.FirstTokenIndex, LastTokenIndex = bexpr.LastTokenIndex, }; return wexpr; } case "UnaryExpression": { var uexpr = scalarExpr as UnaryExpression; var wuexpr = new WUnaryExpression { Expression = ParseScalarExpression(uexpr.Expression), ExpressionType = uexpr.UnaryExpressionType, FirstTokenIndex = uexpr.FirstTokenIndex, LastTokenIndex = uexpr.LastTokenIndex }; return wuexpr; } case "ColumnReferenceExpression": { var cre = scalarExpr as ColumnReferenceExpression; var wexpr = new WColumnReferenceExpression { MultiPartIdentifier = ParseMultiPartIdentifier(cre.MultiPartIdentifier), ColumnType = cre.ColumnType, FirstTokenIndex = cre.FirstTokenIndex, LastTokenIndex = cre.LastTokenIndex }; return wexpr; } case "ScalarSubquery": { var oquery = scalarExpr as ScalarSubquery; var wexpr = new WScalarSubquery { SubQueryExpr = ParseSelectQueryStatement(oquery.QueryExpression), FirstTokenIndex = oquery.FirstTokenIndex, LastTokenIndex = oquery.LastTokenIndex }; return wexpr; } case "ParenthesisExpression": { var parenExpr = scalarExpr as ParenthesisExpression; var wexpr = new WParenthesisExpression { Expression = ParseScalarExpression(parenExpr.Expression), FirstTokenIndex = parenExpr.FirstTokenIndex, LastTokenIndex = parenExpr.LastTokenIndex, }; return wexpr; } case "FunctionCall": { var fc = scalarExpr as FunctionCall; var wexpr = new WFunctionCall { CallTarget = ParseCallTarget(fc.CallTarget), FunctionName = fc.FunctionName, UniqueRowFilter = fc.UniqueRowFilter, FirstTokenIndex = fc.FirstTokenIndex, LastTokenIndex = fc.LastTokenIndex, }; if (fc.Parameters == null) return wexpr; wexpr.Parameters = new List<WScalarExpression>(fc.Parameters.Count); foreach (var pe in fc.Parameters.Select(ParseScalarExpression).Where(pe => pe != null)) { wexpr.Parameters.Add(pe); } return wexpr; } case "SearchedCaseExpression": { var caseExpr = scalarExpr as SearchedCaseExpression; var wexpr = new WSearchedCaseExpression { FirstTokenIndex = caseExpr.FirstTokenIndex, LastTokenIndex = caseExpr.LastTokenIndex, WhenClauses = new List<WSearchedWhenClause>(caseExpr.WhenClauses.Count) }; foreach (var pwhen in caseExpr.WhenClauses.Select(swhen => new WSearchedWhenClause { WhenExpression = ParseBooleanExpression(swhen.WhenExpression), ThenExpression = ParseScalarExpression(swhen.ThenExpression), FirstTokenIndex = swhen.FirstTokenIndex, LastTokenIndex = swhen.LastTokenIndex, })) { wexpr.WhenClauses.Add(pwhen); } wexpr.ElseExpr = ParseScalarExpression(caseExpr.ElseExpression); return wexpr; } case "CastCall": { var castExpr = scalarExpr as CastCall; var wexpr = new WCastCall { DataType = ParseDataType(castExpr.DataType), Parameter = ParseScalarExpression(castExpr.Parameter), FirstTokenIndex = castExpr.FirstTokenIndex, LastTokenIndex = castExpr.LastTokenIndex, }; return wexpr; } default: { if (!(scalarExpr is ValueExpression)) return null; var wexpr = new WValueExpression { FirstTokenIndex = scalarExpr.FirstTokenIndex, LastTokenIndex = scalarExpr.LastTokenIndex, }; var expr = scalarExpr as Literal; if (expr != null) { wexpr.Value = expr.Value; if (expr.LiteralType == LiteralType.String) { wexpr.SingleQuoted = true; } } else { var reference = scalarExpr as VariableReference; wexpr.Value = reference != null ? reference.Name : ((GlobalVariableExpression)scalarExpr).Name; } return wexpr; } } }
internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewCommand command) { WColumnReferenceExpression updateParameter = this.Parameters[0] as WColumnReferenceExpression; int updateIndex = context.LocateColumnReference(updateParameter); List <PropertyTuple> propertiesList = new List <PropertyTuple>(); for (int i = 1; i < this.Parameters.Count; ++i) { WPropertyExpression property = this.Parameters[i] as WPropertyExpression; if (property.Value is WValueExpression) { WValueExpression value = property.Value as WValueExpression; Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> > meta = new Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> >(); foreach (KeyValuePair <WValueExpression, WScalarExpression> pair in property.MetaProperties) { string name = pair.Key.Value; if (pair.Value is WValueExpression) { WValueExpression metaValue = pair.Value as WValueExpression; meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(metaValue.ToStringField(), null)); } else { WScalarSubquery metaScalarSubquery = pair.Value as WScalarSubquery; ScalarSubqueryFunction metaValueFunction = (ScalarSubqueryFunction)metaScalarSubquery.CompileToFunction(context, command); meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(null, metaValueFunction)); } } PropertyTuple valueProperty = new PropertyTuple(property.Cardinality, property.Key.Value, value.ToStringField(), meta); propertiesList.Add(valueProperty); } else { WScalarSubquery scalarSubquery = property.Value as WScalarSubquery; ScalarSubqueryFunction valueFunction = (ScalarSubqueryFunction)scalarSubquery.CompileToFunction(context, command); Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> > meta = new Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> >(); foreach (KeyValuePair <WValueExpression, WScalarExpression> pair in property.MetaProperties) { string name = pair.Key.Value; if (pair.Value is WValueExpression) { WValueExpression metaValue = pair.Value as WValueExpression; meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(metaValue.ToStringField(), null)); } else { WScalarSubquery metaScalarSubquery = pair.Value as WScalarSubquery; ScalarSubqueryFunction metaValueFunction = (ScalarSubqueryFunction)metaScalarSubquery.CompileToFunction(context, command); meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(null, metaValueFunction)); } } PropertyTuple valueProperty = new PropertyTuple(property.Cardinality, property.Key.Value, valueFunction, meta); propertiesList.Add(valueProperty); } } UpdatePropertiesOperator updateOp = new UpdatePropertiesOperator( context.CurrentExecutionOperator, command, updateIndex, propertiesList); context.CurrentExecutionOperator = updateOp; return(updateOp); }
internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewCommand command) { WScalarSubquery srcSubQuery = Parameters[0] as WScalarSubquery; WScalarSubquery sinkSubQuery = Parameters[1] as WScalarSubquery; if (srcSubQuery == null || sinkSubQuery == null) { throw new SyntaxErrorException("The first two parameters of AddE can only be WScalarSubquery."); } Container container = new Container(); QueryCompilationContext srcSubContext = new QueryCompilationContext(context); srcSubContext.OuterContextOp.SetContainer(container); GraphViewExecutionOperator srcSubQueryOp = srcSubQuery.SubQueryExpr.Compile(srcSubContext, command); QueryCompilationContext sinkSubContext = new QueryCompilationContext(context); sinkSubContext.OuterContextOp.SetContainer(container); GraphViewExecutionOperator sinkSubQueryOp = sinkSubQuery.SubQueryExpr.Compile(sinkSubContext, command); WValueExpression otherVTagParameter = Parameters[2] as WValueExpression; Debug.Assert(otherVTagParameter != null, "otherVTagParameter != null"); // // if otherVTag == 0, this newly added edge's otherV() is the src vertex. // Otherwise, it's the sink vertex // int otherVTag = int.Parse(otherVTagParameter.Value); WValueExpression labelValue = (WValueExpression)this.Parameters[3]; List <WPropertyExpression> edgeProperties = new List <WPropertyExpression>(); List <PropertyTuple> subtraversalProperties = new List <PropertyTuple>(); List <string> projectedField = new List <string>(GraphViewReservedProperties.ReservedEdgeProperties); projectedField.Add(GremlinKeyword.Label); for (int i = 4; i < this.Parameters.Count; i++) { WPropertyExpression property = (WPropertyExpression)this.Parameters[i]; Debug.Assert(property != null, "[WAddETableReference.Compile] Edge property should not be null"); Debug.Assert(property.Cardinality == GremlinKeyword.PropertyCardinality.Single, "[WAddETableReference.Compile] Edge property should not be append-mode"); Debug.Assert(property.Value != null); if (!projectedField.Contains(property.Key.Value)) { projectedField.Add(property.Key.Value); } if (property.Value is WValueExpression) { edgeProperties.Add(property); } else { WScalarSubquery scalarSubquery = property.Value as WScalarSubquery; ScalarSubqueryFunction valueFunction = (ScalarSubqueryFunction)scalarSubquery.CompileToFunction(context, command); subtraversalProperties.Add(new PropertyTuple(property.Cardinality, property.Key.Value, valueFunction)); } } JObject edgeJsonObject = ConstructEdgeJsonObject(command, labelValue.Value, edgeProperties); // metadata remains missing GraphViewExecutionOperator addEOp = new AddEOperator(context.CurrentExecutionOperator, command, container, srcSubQueryOp, sinkSubQueryOp, otherVTag, edgeJsonObject, projectedField, subtraversalProperties); context.CurrentExecutionOperator = addEOp; // Update context's record layout context.AddField(Alias.Value, GremlinKeyword.EdgeSourceV, ColumnGraphType.EdgeSource); context.AddField(Alias.Value, GremlinKeyword.EdgeSinkV, ColumnGraphType.EdgeSink); context.AddField(Alias.Value, GremlinKeyword.EdgeOtherV, ColumnGraphType.Value); context.AddField(Alias.Value, GremlinKeyword.EdgeID, ColumnGraphType.EdgeId); context.AddField(Alias.Value, GremlinKeyword.Star, ColumnGraphType.EdgeObject); for (var i = GraphViewReservedProperties.ReservedEdgeProperties.Count; i < projectedField.Count; i++) { context.AddField(Alias.Value, projectedField[i], ColumnGraphType.Value); } return(addEOp); }
/// <summary> /// Creates node table and inserts related metadata. /// </summary> /// <param name="sqlStr">A CREATE TABLE statement with metadata.</param> /// <param name="externalTransaction">An existing SqlTransaction instance under which the create node table will occur.</param> /// <returns>Returns true if the statement is successfully executed.</returns> public bool CreateNodeTable(string sqlStr, SqlTransaction externalTransaction = null) { // get syntax tree of CREATE TABLE command var parser = new GraphViewParser(); List<WNodeTableColumn> columns; IList<ParseError> errors; var script = parser.ParseCreateNodeTableStatement(sqlStr, out columns, out errors) as WSqlScript; if (errors.Count > 0) throw new SyntaxErrorException(errors); if (script == null || script.Batches.Count == 0) { throw new SyntaxErrorException("Invalid CREATE TABLE statement."); } var statement = script.Batches[0].Statements[0] as WCreateTableStatement; var tableSchema = statement.SchemaObjectName.SchemaIdentifier != null ? statement.SchemaObjectName.SchemaIdentifier.Value : "dbo"; var tableName = statement.SchemaObjectName.BaseIdentifier.Value; SqlTransaction tx; if (externalTransaction == null) { tx = Conn.BeginTransaction(); } else { tx = externalTransaction; } // Persists the node table's meta-data try { using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName]) OUTPUT [Inserted].[TableId] VALUES (@tableSchema, @tableName)", MetadataTables[0]); command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); // get generated TableId WValueExpression tableIdentitySeed; using (var reader = command.ExecuteReader()) { if (!reader.Read()) { return false; } var tableId = Convert.ToInt64(reader["TableId"], CultureInfo.CurrentCulture) << 48; tableIdentitySeed = new WValueExpression(tableId.ToString(CultureInfo.InvariantCulture), false); } // create graph table var wColumnDefinition = statement.Definition.ColumnDefinitions .FirstOrDefault(x => x.ColumnIdentifier.Value == "GlobalNodeId"); if (wColumnDefinition != null) wColumnDefinition.IdentityOptions.IdentitySeed = tableIdentitySeed; command.CommandText = statement.ToString(); command.ExecuteNonQuery(); } using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; // insert graph column command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnRole], [Reference]) VALUES (@tableSchema, @tableName, @columnName, @columnRole, @ref)", MetadataTables[1]); command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); command.Parameters.Add("@columnName", SqlDbType.NVarChar, 128); command.Parameters.Add("@columnRole", SqlDbType.Int); command.Parameters.Add("@ref", SqlDbType.NVarChar, 128); //command.Parameters["@columnName"].Value = "NodeId"; //command.Parameters["@columnRole"].Value = (int) WGraphTableColumnRole.NodeId; //command.Parameters["@ref"].Value = SqlChars.Null; //command.ExecuteNonQuery(); foreach (var column in columns) { command.Parameters["@columnName"].Value = column.ColumnName.Value; command.Parameters["@columnRole"].Value = (int) column.ColumnRole; var edgeColumn = column as WGraphTableEdgeColumn; if (edgeColumn != null) { command.Parameters["@ref"].Value = (edgeColumn.TableReference as WNamedTableReference).ExposedName.Value; } else { command.Parameters["@ref"].Value = SqlChars.Null; } command.ExecuteNonQuery(); } command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [AverageDegree]) VALUES (@tableSchema, @tableName, @columnName, @AverageDegree)", MetadataTables[3]); command.Parameters.Add("@AverageDegree", SqlDbType.Int); command.Parameters["@AverageDegree"].Value = 5; foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) { command.Parameters["@columnName"].Value = column.ColumnName.Value; command.ExecuteNonQuery(); } } // insert graph edge attributes using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [AttributeName], [AttributeType], [AttributeEdgeId]) VALUES (@tableSchema, @tableName, @columnName, @attrName, @attrType, @attrId)", MetadataTables[2]); command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); command.Parameters.Add("@columnName", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrName", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrType", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrId", SqlDbType.Int); var createOrder = 1; foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) { command.Parameters["@columnName"].Value = column.ColumnName.Value; foreach (var attr in column.Attributes) { command.Parameters["@attrName"].Value = attr.Item1.Value; command.Parameters["@attrType"].Value = attr.Item2.ToString(); command.Parameters["@attrId"].Value = (createOrder++).ToString(); command.ExecuteNonQuery(); } } } // create column edge sampling table // using (var command = new SqlCommand(null, Conn)) // { // command.Transaction = tx; // foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) // { // command.CommandText = String.Format(CultureInfo.CurrentCulture, @" // CREATE TABLE [{0}_{1}_{2}_Sampling] ( // [src] [bigint], // [dst] [bigint] // )", tableSchema, tableName, column.ColumnName.Value); // command.ExecuteNonQuery(); // } // } // process edge's Decoder function //var edgeDict = columns.OfType<WGraphTableEdgeColumn>() // .ToDictionary(col => col.ColumnName.Value, // col => // col.Attributes.Select( // x => // new Tuple<string, string>(x.Item1.Value, // x.Item2.ToString().ToLower(CultureInfo.CurrentCulture))) // .ToList()); var edgeDict = columns.OfType<WGraphTableEdgeColumn>() .Select( col => new Tuple<string, bool, List<Tuple<string, string>>>(col.ColumnName.Value, String.Equals(tableName, (col.TableReference as WNamedTableReference).ExposedName.Value, StringComparison.CurrentCultureIgnoreCase), col.Attributes.Select( x => new Tuple<string, string>(x.Item1.Value, x.Item2.ToString().ToLower(CultureInfo.CurrentCulture))) .ToList())).ToList(); if (edgeDict.Count > 0) { var assemblyName = tableSchema + '_' + tableName; GraphViewDefinedFunctionGenerator.NodeTableRegister(assemblyName, tableName, edgeDict, Conn, tx); } using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) { command.CommandText = String.Format(CultureInfo.CurrentCulture, @" SELECT * INTO [{0}_{1}_{2}_Sampling] FROM ( SELECT ([GlobalNodeID]+0) as [Src], [Edge].* FROM [{0}].[{1}] WITH (NOLOCK) CROSS APPLY {0}_{1}_{2}_Decoder([{2}],[{2}DeleteCol]) AS Edge WHERE 1=0) as EdgeSample", tableSchema, tableName, column.ColumnName.Value); command.ExecuteNonQuery(); } } if (externalTransaction == null) { tx.Commit(); } return true; } catch (SqlException e) { if (externalTransaction == null) { tx.Rollback(); } throw new SqlExecutionException("An error occurred when creating the node table.", e); } }
public virtual void Visit(WValueExpression node) { node.AcceptChildren(this); }
public override void Visit(WValueExpression node) { this.dfsStack.Push(node.ToString("")); }
internal override GraphViewExecutionOperator Compile(QueryCompilationContext context, GraphViewCommand command) { // // Parameters: // #1 <WValueExpression>: Vertex label // ... <WPropertyExpression>: The initial properties on vertex // WValueExpression labelValue = (WValueExpression)this.Parameters[0]; Debug.Assert(labelValue.Value != null, "[WAddVTableReference.Compile] Vertex label should not be null"); List <PropertyTuple> vertexProperties = new List <PropertyTuple>(); List <string> projectedField = new List <string>(GraphViewReservedProperties.InitialPopulateNodeProperties); projectedField.Add(GremlinKeyword.Star); projectedField.Add(GremlinKeyword.Label); for (int i = 1; i < this.Parameters.Count; i++) { WPropertyExpression property = (WPropertyExpression)this.Parameters[i]; Debug.Assert(property != null, "[WAddVTableReference.Compile] Vertex property should not be null"); Debug.Assert(property.Cardinality == GremlinKeyword.PropertyCardinality.List, "[WAddVTableReference.Compile] Vertex property should be append-mode"); Debug.Assert(property.Value != null); if (!projectedField.Contains(property.Key.Value)) { projectedField.Add(property.Key.Value); } if (property.Value is WValueExpression) { WValueExpression value = property.Value as WValueExpression; Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> > meta = new Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> >(); foreach (KeyValuePair <WValueExpression, WScalarExpression> pair in property.MetaProperties) { string name = pair.Key.Value; if (pair.Value is WValueExpression) { WValueExpression metaValue = pair.Value as WValueExpression; meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(metaValue.ToStringField(), null)); } else { WScalarSubquery metaScalarSubquery = pair.Value as WScalarSubquery; ScalarSubqueryFunction metaValueFunction = (ScalarSubqueryFunction)metaScalarSubquery.CompileToFunction(context, command); meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(null, metaValueFunction)); } } PropertyTuple valueProperty = new PropertyTuple(property.Cardinality, property.Key.Value, value.ToStringField(), meta); vertexProperties.Add(valueProperty); } else { WScalarSubquery scalarSubquery = property.Value as WScalarSubquery; ScalarSubqueryFunction valueFunction = (ScalarSubqueryFunction)scalarSubquery.CompileToFunction(context, command); Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> > meta = new Dictionary <string, Tuple <StringField, ScalarSubqueryFunction> >(); foreach (KeyValuePair <WValueExpression, WScalarExpression> pair in property.MetaProperties) { string name = pair.Key.Value; if (pair.Value is WValueExpression) { WValueExpression metaValue = pair.Value as WValueExpression; meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(metaValue.ToStringField(), null)); } else { WScalarSubquery metaScalarSubquery = pair.Value as WScalarSubquery; ScalarSubqueryFunction metaValueFunction = (ScalarSubqueryFunction)metaScalarSubquery.CompileToFunction(context, command); meta.Add(name, new Tuple <StringField, ScalarSubqueryFunction>(null, metaValueFunction)); } } PropertyTuple valueProperty = new PropertyTuple(property.Cardinality, property.Key.Value, valueFunction, meta); vertexProperties.Add(valueProperty); } } JObject nodeJsonDocument = ConstructNodeJsonDocument(command, labelValue.Value); AddVOperator addVOp = new AddVOperator( context.CurrentExecutionOperator, command, nodeJsonDocument, projectedField, vertexProperties); context.CurrentExecutionOperator = addVOp; for (int i = 0; i < projectedField.Count; i++) { string propertyName = projectedField[i]; ColumnGraphType columnGraphType = GraphViewReservedProperties.IsNodeReservedProperty(propertyName) ? GraphViewReservedProperties.ReservedNodePropertiesColumnGraphTypes[propertyName] : ColumnGraphType.Value; context.AddField(Alias.Value, propertyName, columnGraphType); } // Convert the connection to Hybrid if necessary if (command.Connection.GraphType != GraphType.GraphAPIOnly) { command.Connection.GraphType = GraphType.Hybrid; } return(addVOp); }
private bool IsOptionNone(WValueExpression option) { return(!option.SingleQuoted && option.Value.Equals("null", StringComparison.OrdinalIgnoreCase)); }
/// <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, } }); }
internal override RawRecord DataModify(RawRecord record) { long edgeOffset = long.Parse(record[this._edgeOffsetIndex].ToValue); string srcVertexId = record[this._srcVertexIdIndex].ToValue; JObject srcVertexObject = this.Connection.RetrieveDocumentById(srcVertexId); string outEdgeDocId; JObject outEdgeObject; EdgeDocumentHelper.FindEdgeBySourceAndOffset( this.Connection, srcVertexObject, srcVertexId, edgeOffset, false, out outEdgeObject, out outEdgeDocId); if (outEdgeObject == null) { // TODO: Is there something wrong? Debug.WriteLine($"[UpdateEdgePropertiesOperator] The edge does not exist: vertexId = {srcVertexId}, edgeOffset = {edgeOffset}"); return(null); } string sinkVertexId = (string)outEdgeObject["_sinkV"]; JObject sinkVertexObject; string inEdgeDocId; JObject inEdgeObject; if (sinkVertexId.Equals(srcVertexId)) { sinkVertexObject = srcVertexObject; // NOTE: Must not use DeepClone() here! } else { sinkVertexObject = this.Connection.RetrieveDocumentById(sinkVertexId); } EdgeDocumentHelper.FindEdgeBySourceAndOffset( this.Connection, sinkVertexObject, srcVertexId, edgeOffset, true, out inEdgeObject, out inEdgeDocId); VertexField srcVertexField = this.Connection.VertexCache.GetVertexField(srcVertexId); VertexField sinkVertexField = this.Connection.VertexCache.GetVertexField(sinkVertexId); EdgeField outEdgeField = srcVertexField.AdjacencyList.GetEdgeField(srcVertexId, edgeOffset); EdgeField inEdgeField = sinkVertexField.RevAdjacencyList.GetEdgeField(srcVertexId, edgeOffset); // Drop all non-reserved properties if (this.PropertiesToBeUpdated.Count == 1 && !this.PropertiesToBeUpdated[0].Item1.SingleQuoted && this.PropertiesToBeUpdated[0].Item1.Value.Equals("*", StringComparison.OrdinalIgnoreCase) && !this.PropertiesToBeUpdated[0].Item2.SingleQuoted && this.PropertiesToBeUpdated[0].Item2.Value.Equals("null", StringComparison.OrdinalIgnoreCase)) { List <string> toBeDroppedProperties = GraphViewJsonCommand.DropAllEdgeProperties(outEdgeObject); foreach (var propertyName in toBeDroppedProperties) { outEdgeField.EdgeProperties.Remove(propertyName); } toBeDroppedProperties = GraphViewJsonCommand.DropAllEdgeProperties(inEdgeObject); foreach (var propertyName in toBeDroppedProperties) { inEdgeField.EdgeProperties.Remove(propertyName); } } else { foreach (Tuple <WValueExpression, WValueExpression, int> tuple in this.PropertiesToBeUpdated) { WValueExpression keyExpression = tuple.Item1; WValueExpression valueExpression = tuple.Item2; if (this.Mode == UpdatePropertyMode.Set) { // Modify edgeObject (update the edge property) JProperty updatedProperty = GraphViewJsonCommand.UpdateProperty(outEdgeObject, keyExpression, valueExpression); // Update VertexCache if (updatedProperty == null) { outEdgeField.EdgeProperties.Remove(keyExpression.Value); } else { outEdgeField.UpdateEdgeProperty(updatedProperty, outEdgeField); } // Modify edgeObject (update the edge property) updatedProperty = GraphViewJsonCommand.UpdateProperty(inEdgeObject, keyExpression, valueExpression); // Update VertexCache if (updatedProperty == null) { inEdgeField.EdgeProperties.Remove(keyExpression.Value); } else { inEdgeField.UpdateEdgeProperty(updatedProperty, inEdgeField); } } else { throw new NotImplementedException(); } } } // Interact with DocDB to update the property EdgeDocumentHelper.UpdateEdgeProperty(this.Connection, srcVertexObject, outEdgeDocId, false, outEdgeObject); EdgeDocumentHelper.UpdateEdgeProperty(this.Connection, sinkVertexObject, inEdgeDocId, true, inEdgeObject); // // Drop edge property // if (this.PropertiesToBeUpdated.Any(t => t.Item2 == null)) { return(null); } return(record); }
/// <summary> /// Creates a node table in the graph database. /// </summary> /// <param name="sqlStr">A CREATE TABLE statement with annotations.</param> /// <param name="externalTransaction">An existing SqlTransaction instance under which the create node table will occur.</param> /// <returns>True, if the statement is successfully executed.</returns> public bool CreateNodeTable(string sqlStr, SqlTransaction externalTransaction = null) { // get syntax tree of CREATE TABLE command var parser = new GraphViewParser(); List<WNodeTableColumn> columns; IList<ParseError> errors; var script = parser.ParseCreateNodeTableStatement(sqlStr, out columns, out errors) as WSqlScript; if (errors.Count > 0) throw new SyntaxErrorException(errors); if (script == null || script.Batches.Count == 0) { throw new SyntaxErrorException("Invalid CREATE TABLE statement."); } var statement = script.Batches[0].Statements[0] as WCreateTableStatement; var tableSchema = statement.SchemaObjectName.SchemaIdentifier != null ? statement.SchemaObjectName.SchemaIdentifier.Value : "dbo"; var tableName = statement.SchemaObjectName.BaseIdentifier.Value; SqlTransaction tx; if (externalTransaction == null) { tx = Conn.BeginTransaction(); } else { tx = externalTransaction; } // Persists the node table's meta-data try { Int64 tableId; using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName]) OUTPUT [Inserted].[TableId] VALUES (@tableSchema, @tableName)", MetadataTables[0]); command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); // get generated TableId WValueExpression tableIdentitySeed; using (var reader = command.ExecuteReader()) { if (!reader.Read()) { return false; } tableId = Convert.ToInt64(reader["TableId"], CultureInfo.CurrentCulture); var tableIdSeek = tableId << 48; tableIdentitySeed = new WValueExpression(tableIdSeek.ToString(CultureInfo.InvariantCulture), false); } // create graph table var wColumnDefinition = statement.Definition.ColumnDefinitions .FirstOrDefault(x => x.ColumnIdentifier.Value == "GlobalNodeId"); if (wColumnDefinition != null) wColumnDefinition.IdentityOptions.IdentitySeed = tableIdentitySeed; command.CommandText = statement.ToString(); command.ExecuteNonQuery(); } var edgeColumnNameToColumnId = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase); var hasReversedEdge = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; // insert graph column command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [TableId], [ColumnName], [ColumnRole], [Reference], [HasReversedEdge], [EdgeUdfPrefix]) OUTPUT [Inserted].[ColumnId] VALUES (@tableSchema, @tableName, @tableid, @columnName, @columnRole, @ref, @hasRevEdge, @udfPrefix)", MetadataTables[1]); command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); command.Parameters.AddWithValue("@tableid", tableId); command.Parameters.Add("@columnName", SqlDbType.NVarChar, 128); command.Parameters.Add("@columnRole", SqlDbType.Int); command.Parameters.Add("@ref", SqlDbType.NVarChar, 128); command.Parameters.Add("@hasRevEdge", SqlDbType.Bit); command.Parameters.Add("@udfPrefix", SqlDbType.NVarChar, 512); foreach (var column in columns) { command.Parameters["@columnName"].Value = column.ColumnName.Value; command.Parameters["@columnRole"].Value = (int) column.ColumnRole; command.Parameters["@hasRevEdge"].Value = column.ColumnRole == WNodeTableColumnRole.Edge ? 1 : 0; var edgeColumn = column as WGraphTableEdgeColumn; if (edgeColumn != null) { command.Parameters["@ref"].Value = (edgeColumn.TableReference as WNamedTableReference).ExposedName.Value; command.Parameters["@udfPrefix"].Value = tableSchema + "_" + tableName + "_" + column.ColumnName.Value; } else { command.Parameters["@ref"].Value = command.Parameters["@udfPrefix"].Value = SqlChars.Null; } using (var reader = command.ExecuteReader()) { if (!reader.Read()) { return false; } if (column.ColumnRole == WNodeTableColumnRole.Edge) { edgeColumnNameToColumnId[column.ColumnName.Value] = Convert.ToInt64(reader["ColumnId"].ToString(), CultureInfo.CurrentCulture); hasReversedEdge[column.ColumnName.Value] = true; } } } command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnId], [AverageDegree]) VALUES (@tableSchema, @tableName, @columnName, @columnid, @AverageDegree)", MetadataTables[3]); command.Parameters.Add("@AverageDegree", SqlDbType.Int); command.Parameters["@AverageDegree"].Value = 5; command.Parameters.Add("@columnid", SqlDbType.Int); foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) { command.Parameters["@columnid"].Value = edgeColumnNameToColumnId[column.ColumnName.Value]; command.Parameters["@columnName"].Value = column.ColumnName.Value; command.ExecuteNonQuery(); } } // insert graph edge attributes using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnId], [AttributeName], [AttributeType], [AttributeEdgeId]) VALUES (@tableSchema, @tableName, @columnName, @columnid, @attrName, @attrType, @attrId)", MetadataTables[2]); command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); command.Parameters.Add("@columnName", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrName", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrType", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrId", SqlDbType.Int); command.Parameters.Add("@columnid", SqlDbType.Int); var createOrder = 1; foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) { command.Parameters["@columnName"].Value = column.ColumnName.Value; foreach (var attr in column.Attributes) { command.Parameters["@attrName"].Value = attr.Item1.Value; command.Parameters["@attrType"].Value = attr.Item2.ToString(); command.Parameters["@attrId"].Value = (createOrder++).ToString(); command.Parameters["@columnid"].Value = edgeColumnNameToColumnId[column.ColumnName.Value]; command.ExecuteNonQuery(); } } } // create column edge sampling table // using (var command = new SqlCommand(null, Conn)) // { // command.Transaction = tx; // foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) // { // command.CommandText = String.Format(CultureInfo.CurrentCulture, @" // CREATE TABLE [{0}_{1}_{2}_Sampling] ( // [src] [bigint], // [dst] [bigint] // )", tableSchema, tableName, column.ColumnName.Value); // command.ExecuteNonQuery(); // } // } // process edge's Decoder function //var edgeDict = columns.OfType<WGraphTableEdgeColumn>() // .ToDictionary(col => col.ColumnName.Value, // col => // col.Attributes.Select( // x => // new Tuple<string, string>(x.Item1.Value, // x.Item2.ToString().ToLower(CultureInfo.CurrentCulture))) // .ToList()); var edgeDict = columns.OfType<WGraphTableEdgeColumn>() .Select( col => new Tuple<string,int, List<Tuple<string, string>>>(col.ColumnName.Value, (int)edgeColumnNameToColumnId[col.ColumnName.Value], col.Attributes.Select( x => new Tuple<string, string>(x.Item1.Value, x.Item2.ToString().ToLower(CultureInfo.CurrentCulture))) .ToList())).ToList(); var userIdColumn = columns.Where(e => e.ColumnRole == WNodeTableColumnRole.NodeId).ToList(); string userId = (userIdColumn.Count == 0) ? "" : userIdColumn[0].ColumnName.Value; if (edgeDict.Count > 0) { var assemblyName = tableSchema + '_' + tableName; GraphViewDefinedFunctionRegister register = new NodeTableRegister(assemblyName, tableName, edgeDict, userId); register.Register(Conn, tx); } using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; foreach (var column in columns.OfType<WGraphTableEdgeColumn>()) { command.CommandText = String.Format(CultureInfo.CurrentCulture, @" SELECT * INTO [{0}_{1}_{2}_Sampling] FROM ( SELECT ([GlobalNodeID]+0) as [Src], [Edge].* FROM [{0}].[{1}] WITH (NOLOCK) CROSS APPLY {0}_{1}_{2}_Decoder([{2}],[{2}DeleteCol],0) AS Edge WHERE 1=0) as EdgeSample", tableSchema, tableName, column.ColumnName.Value); command.ExecuteNonQuery(); } } //updateGlobalNodeView(tableSchema, tx); // check whether adding reversed edges into the current node table column collection are required var reversedEdgeCommandText = String.Empty; var reversedEdgeSamplingCommandText = String.Empty; var reversedMetaCommandTextList = new List<string>(); using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; command.CommandText = String.Format(@" SELECT [ColumnId], [TableSchema], [TableName], [ColumnName], [ColumnRole], [Reference], [HasReversedEdge], [EdgeUdfPrefix] FROM [{0}] WHERE [ColumnRole] = 1 AND [Reference] = '{1}'", MetadataTables[1], tableName); var originalColumnIdList = new List<long>(); using (var reader = command.ExecuteReader()) { var index = 0; while (reader.Read()) { if (!bool.Parse(reader["HasReversedEdge"].ToString())) continue; var sourceTableSchema = reader["TableSchema"].ToString(); var sourceTableName = reader["TableName"].ToString(); var sourceEdgeName = reader["ColumnName"].ToString(); var reversedEdgeName = sourceTableName + "_" + sourceEdgeName + "Reversed"; var parameters = new string[] { "@tableSchema" + index, "@tableName" + index, "@tableid" + index, "@columnName" + index, "@columnRole" + index, "@ref" + index, "@refTableSchema" + index, "@isRevEdge" + index, "@udfPrefix" + index }; // add reversed edge varbinary columns reversedEdgeCommandText += String.Format(@" ALTER TABLE [{0}].[{1}] ADD [{2}] VARBINARY(MAX) NOT NULL DEFAULT 0x, [{3}] VARBINARY(MAX) NOT NULL DEFAULT 0x, [{4}] INT NOT NULL DEFAULT 0; ", tableSchema, tableName, reversedEdgeName, reversedEdgeName + "DeleteCol", reversedEdgeName + "OutDegree"); // create reversed edge sampling table reversedEdgeSamplingCommandText += String.Format(@" SELECT * INTO [{0}_{1}_{2}_Sampling] FROM ( SELECT ([GlobalNodeID]+0) as [Src], [Edge].* FROM [{0}].[{1}] WITH (NOLOCK) CROSS APPLY {3}_{4}_{5}_Decoder([{2}],[{2}DeleteCol],0) AS Edge WHERE 1=0) as EdgeSample ", tableSchema, tableName, reversedEdgeName, sourceTableSchema, sourceTableName, sourceEdgeName); // update meta info about reversed edges reversedMetaCommandTextList.Add(string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [TableId], [ColumnName], [ColumnRole], [Reference], [RefTableSchema], [IsReversedEdge], [EdgeUdfPrefix]) OUTPUT [Inserted].[ColumnId] VALUES ({1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}) ", MetadataTables[1], parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8])); command.Parameters.AddWithValue(parameters[0], tableSchema); command.Parameters.AddWithValue(parameters[1], tableName); command.Parameters.AddWithValue(parameters[2], tableId); command.Parameters.AddWithValue(parameters[3], reversedEdgeName); command.Parameters.AddWithValue(parameters[4], Convert.ToInt32(reader["ColumnRole"].ToString(), CultureInfo.CurrentCulture)); command.Parameters.AddWithValue(parameters[5], sourceTableName); command.Parameters.AddWithValue(parameters[6], sourceTableSchema); command.Parameters.AddWithValue(parameters[7], 1); command.Parameters.AddWithValue(parameters[8], reader["EdgeUdfPrefix"].ToString()); originalColumnIdList.Add(Convert.ToInt64(reader["ColumnId"].ToString(), CultureInfo.CurrentCulture)); ++index; } } if (String.IsNullOrEmpty(reversedEdgeCommandText) == false) { command.CommandText = reversedEdgeCommandText; command.ExecuteNonQuery(); command.CommandText = reversedEdgeSamplingCommandText; command.ExecuteNonQuery(); command.CommandText = String.Format(@" SELECT MAX([AttributeEdgeId]) AS maxAttrEdgeId FROM [{0}] WHERE [TableSchema] = '{1}' AND [TableName] = '{2}'", MetadataTables[2], tableSchema, tableName); var createOrder = 1; using (var reader = command.ExecuteReader()) { if (reader.Read()) { var startOrder = reader["maxAttrEdgeId"].ToString(); createOrder = String.IsNullOrEmpty(startOrder) ? 1 : Convert.ToInt32(startOrder, CultureInfo.CurrentCulture) + 1; } } // NodeTableColumnCollection update for (var i = 0; i < reversedMetaCommandTextList.Count; ++i) { command.CommandText = reversedMetaCommandTextList[i]; if (command.Parameters.Contains("@tableSchema")) { command.Parameters.RemoveAt("@tableSchema"); command.Parameters.RemoveAt("@tableName"); command.Parameters.RemoveAt("@columnName"); command.Parameters.RemoveAt("@columnid"); command.Parameters.RemoveAt("@AverageDegree"); if (command.Parameters.Contains("@attrName")) { command.Parameters.RemoveAt("@attrName"); command.Parameters.RemoveAt("@attrType"); command.Parameters.RemoveAt("@attrId"); } } long reversedColumnId = 0; using (var reader = command.ExecuteReader()) { if (!reader.Read()) { return false; } if (Convert.ToInt32(command.Parameters["@columnRole"+i].Value, CultureInfo.CurrentCulture) == 1) { reversedColumnId = Convert.ToInt64(reader["ColumnId"].ToString(), CultureInfo.CurrentCulture); } } // EdgeAverageDegreeCollection update command.Parameters.AddWithValue("@tableSchema", tableSchema); command.Parameters.AddWithValue("@tableName", tableName); command.Parameters.AddWithValue("@columnName", command.Parameters["@columnName" + i].Value.ToString()); command.Parameters.Add("@columnid", SqlDbType.Int); command.Parameters["@columnid"].Value = reversedColumnId; command.Parameters.Add("@AverageDegree", SqlDbType.Int); command.Parameters["@AverageDegree"].Value = 5; command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnId], [AverageDegree]) VALUES (@tableSchema, @tableName, @columnName, @columnid, @AverageDegree)", MetadataTables[3]); command.ExecuteNonQuery(); // get all original attributes var attributes = new List<Tuple<string, string>>(); command.CommandText = String.Format(@" SELECT [AttributeName], [AttributeType] FROM [{0}] WHERE [ColumnId] = {1}", MetadataTables[2], originalColumnIdList[i]); using (var reader = command.ExecuteReader()) { while (reader.Read()) { attributes.Add(new Tuple<string, string>( reader["AttributeName"].ToString(), reader["AttributeType"].ToString())); } } if (attributes.Count == 0) continue; // EdgeAttributeCollection update command.Parameters.Add("@attrName", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrType", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrId", SqlDbType.Int); foreach (var attr in attributes) { command.Parameters["@attrName"].Value = attr.Item1; command.Parameters["@attrType"].Value = attr.Item2; command.Parameters["@attrId"].Value = (createOrder++).ToString(); command.CommandText = String.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnId], [AttributeName], [AttributeType], [AttributeEdgeId]) VALUES (@tableSchema, @tableName, @columnName, @columnid, @attrName, @attrType, @attrId)", MetadataTables[2]); command.ExecuteNonQuery(); } } } } // check whether adding reverse edges to pointed node tables are required using (var command = new SqlCommand(null, Conn)) { command.Transaction = tx; foreach (var column in columns.Where(x=>hasReversedEdge.ContainsKey(x.ColumnName.Value))) { command.Parameters.Clear(); reversedEdgeCommandText = reversedEdgeSamplingCommandText = String.Empty; var edgeColumn = column as WGraphTableEdgeColumn; if (edgeColumn == null) continue; var refTableName = (edgeColumn.TableReference as WNamedTableReference).ExposedName.Value; string refTableSchema = String.Empty, reversedEdgeName = String.Empty; Int64 refTableId = 0; // skip the edge which connects to the node table itself if (refTableName.Equals(tableName)) continue; command.CommandText = String.Format(@" SELECT [TableId], [TableSchema], [TableName] FROM [{0}] WHERE [TableRole] = 0 AND [TableName] = '{1}'", MetadataTables[0], refTableName); using (var reader = command.ExecuteReader()) { // if the target node table exists if (reader.Read()) { refTableSchema = reader["TableSchema"].ToString(); reversedEdgeName = tableName + "_" + column.ColumnName.Value + "Reversed"; // add reversed edge varbinary column reversedEdgeCommandText += String.Format(@" ALTER TABLE [{0}].[{1}] ADD [{2}] VARBINARY(MAX) NOT NULL DEFAULT 0x, [{3}] VARBINARY(MAX) NOT NULL DEFAULT 0x, [{4}] INT NOT NULL DEFAULT 0 ", refTableSchema, refTableName, reversedEdgeName, reversedEdgeName + "DeleteCol", reversedEdgeName + "OutDegree"); // create reversed edge sampling table reversedEdgeSamplingCommandText += String.Format(@" SELECT * INTO [{0}_{1}_{2}_Sampling] FROM ( SELECT ([GlobalNodeID]+0) as [Src], [Edge].* FROM [{0}].[{1}] WITH (NOLOCK) CROSS APPLY {3}_{4}_{5}_Decoder([{2}],[{2}DeleteCol],0) AS Edge WHERE 1=0) as EdgeSample ", refTableSchema, refTableName, reversedEdgeName, tableSchema, tableName, column.ColumnName.Value); refTableId = Convert.ToInt64(reader["TableId"], CultureInfo.CurrentCulture); } } // update meta info about reversed edge if (String.IsNullOrEmpty(reversedEdgeCommandText) == false) { command.CommandText = reversedEdgeCommandText; command.ExecuteNonQuery(); command.CommandText = reversedEdgeSamplingCommandText; command.ExecuteNonQuery(); // NodeTableColumnCollection update command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [TableId], [ColumnName], [ColumnRole], [Reference], [RefTableSchema], [IsReversedEdge], [EdgeUdfPrefix]) OUTPUT [Inserted].[ColumnId] VALUES (@tableSchema, @tableName, @tableid, @columnName, @columnRole, @ref, @refTableSchema, @isRevEdge, @udfPrefix)", MetadataTables[1]); command.Parameters.AddWithValue("@tableSchema", refTableSchema); command.Parameters.AddWithValue("@tableName", refTableName); command.Parameters.AddWithValue("@tableid", refTableId); command.Parameters.AddWithValue("@columnName", reversedEdgeName); command.Parameters.AddWithValue("@columnRole", (int)column.ColumnRole); command.Parameters.AddWithValue("@ref", tableName); command.Parameters.AddWithValue("@refTableSchema", tableSchema); command.Parameters.AddWithValue("@isRevEdge", 1); command.Parameters.AddWithValue("@udfPrefix", tableSchema + "_" + tableName + "_" + column.ColumnName.Value); long reversedColumnId = 0; using (var reader = command.ExecuteReader()) { if (!reader.Read()) { return false; } if (column.ColumnRole == WNodeTableColumnRole.Edge) { reversedColumnId = Convert.ToInt64(reader["ColumnId"].ToString(), CultureInfo.CurrentCulture); } } // EdgeAverageDegreeCollection update command.Parameters.Add("@columnid", SqlDbType.Int); command.Parameters["@columnid"].Value = reversedColumnId; command.Parameters.Add("@AverageDegree", SqlDbType.Int); command.Parameters["@AverageDegree"].Value = 5; command.CommandText = string.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnId], [AverageDegree]) VALUES (@tableSchema, @tableName, @columnName, @columnid, @AverageDegree)", MetadataTables[3]); command.ExecuteNonQuery(); command.CommandText = String.Format(@" SELECT MAX([AttributeEdgeId]) AS maxAttrEdgeId FROM [{0}] WHERE [TableSchema] = '{1}' AND [TableName] = '{2}'", MetadataTables[2], refTableSchema, refTableName); var createOrder = 1; using (var reader = command.ExecuteReader()) { if (reader.Read()) { var startOrder = reader["maxAttrEdgeId"].ToString(); createOrder = String.IsNullOrEmpty(startOrder) ? 1 : Convert.ToInt32(startOrder, CultureInfo.CurrentCulture) + 1; } } // EdgeAttributeCollection update command.Parameters.Add("@attrName", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrType", SqlDbType.NVarChar, 128); command.Parameters.Add("@attrId", SqlDbType.Int); foreach (var attr in edgeColumn.Attributes) { command.Parameters["@attrName"].Value = attr.Item1.Value; command.Parameters["@attrType"].Value = attr.Item2.ToString(); command.Parameters["@attrId"].Value = (createOrder++).ToString(); command.CommandText = String.Format(@" INSERT INTO [{0}] ([TableSchema], [TableName], [ColumnName], [ColumnId], [AttributeName], [AttributeType], [AttributeEdgeId]) VALUES (@tableSchema, @tableName, @columnName, @columnid, @attrName, @attrType, @attrId)", MetadataTables[2]); command.ExecuteNonQuery(); } } } } UpdateGlobalNodeView(tableSchema, tx); if (externalTransaction == null) { tx.Commit(); } return true; } catch (SqlException e) { if (externalTransaction == null) { tx.Rollback(); } throw new SqlExecutionException("An error occurred when creating the node table.\n" + e.Message, e); } }
/// <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, } }; }
internal override ScalarFunction CompileToFunction(QueryCompilationContext context, GraphViewCommand command) { string funcName = FunctionName.ToString().ToLowerInvariant(); switch (funcName) { case "withinarray": WColumnReferenceExpression checkField = Parameters[0] as WColumnReferenceExpression; WColumnReferenceExpression arrayField = Parameters[1] as WColumnReferenceExpression; return(new WithInArray(context.LocateColumnReference(checkField), context.LocateColumnReference(arrayField))); case "withoutarray": checkField = Parameters[0] as WColumnReferenceExpression; arrayField = Parameters[1] as WColumnReferenceExpression; return(new WithOutArray(context.LocateColumnReference(checkField), context.LocateColumnReference(arrayField))); case "hasproperty": checkField = Parameters[0] as WColumnReferenceExpression; WValueExpression propertyName = Parameters[1] as WValueExpression; return(new HasProperty(context.LocateColumnReference(checkField), propertyName.Value)); case "compose1": List <Tuple <string, int> > targetFieldsAndTheirNames = new List <Tuple <string, int> >(); WValueExpression defaultProjectionKey = Parameters[1] as WValueExpression; if (defaultProjectionKey == null) { throw new SyntaxErrorException("The first parameter of Compose1 has to be a WValueExpression."); } for (int i = 0; i < Parameters.Count; i += 2) { WColumnReferenceExpression columnRef = Parameters[i] as WColumnReferenceExpression; WValueExpression name = Parameters[i + 1] as WValueExpression; if (name == null) { throw new SyntaxErrorException("The parameter of Compose1 at an even position has to be a WValueExpression."); } if (columnRef == null) { throw new SyntaxErrorException("The parameter of Compose1 at an odd position has to be a WColumnReference."); } targetFieldsAndTheirNames.Add(new Tuple <string, int>(name.Value, context.LocateColumnReference(columnRef))); } return(new ComposeCompositeField(targetFieldsAndTheirNames, defaultProjectionKey.Value)); case "compose2": List <ScalarFunction> inputOfCompose2 = new List <ScalarFunction>(); foreach (var parameter in Parameters) { inputOfCompose2.Add(parameter.CompileToFunction(context, command)); } return(new Compose2(inputOfCompose2)); case "path": List <Tuple <ScalarFunction, bool, HashSet <string> > > pathStepList; List <ScalarFunction> byFuncList; WPathTableReference.GetPathStepListAndByFuncList(context, command, this.Parameters, out pathStepList, out byFuncList); return(new Path(pathStepList)); default: throw new NotImplementedException("Function " + funcName + " hasn't been implemented."); } throw new NotImplementedException("Function " + funcName + " hasn't been implemented."); }