//public virtual WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, GraphMetaData metaData) //{ // var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; // var edgeColIdentifier = edgeIdentifiers.Last(); // var edgeColName = edgeColIdentifier.Value; // HashSet<string> nodeSet; // if (!metaData.NodeViewMapping.TryGetValue( // WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) // nodeSet = null; // NodeColumns columnInfo = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)][ // edgeColIdentifier.Value]; // EdgeInfo edgeInfo = columnInfo.EdgeInfo; // List<Tuple<string, string>> edgeTuples = edgeInfo.EdgeColumns; // var parameters = ConstructEdgeTvfParameters(nodeAlias, "", nodeSet, edgeTuples); // //var isRevEdge = columnInfo.IsReversedEdge; // //string refTableName = null, originalEdgeName = null; // //if (isRevEdge) // //{ // // var index = edgeColName.IndexOf('_'); // // refTableName = edgeColName.Substring(0, index); // // originalEdgeName = edgeColName.Substring(index + 1, // // edgeColName.Length - "Reversed".Length - index - 1); // //} // //var decoderSchemaName = isRevEdge ? columnInfo.RefTableSchema : BindNodeTableObjName.SchemaIdentifier.Value; // //var decoderTableName = isRevEdge ? refTableName : BindNodeTableObjName.BaseIdentifier.Value; // //var decoderEdgeName = isRevEdge ? originalEdgeName : EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value; // //var decoderStr = decoderSchemaName + "_" + decoderTableName + "_" + decoderEdgeName + "_Decoder"; // var decoderFunction = new Identifier // { // Value = edgeInfo.EdgeUdfPrefix + "_Decoder", // }; // return new WSchemaObjectFunctionTableReference // { // SchemaObject = new WSchemaObjectName( // new Identifier { Value = "dbo" }, // decoderFunction), // Parameters = parameters, // Alias = new Identifier // { // Value = EdgeAlias, // } // }; //} /// <summary> /// Converts the edge to the table-valued function /// </summary> /// <param name="nodeAlias">Source node alias</param> /// <param name="dumbNode">Dumb node parameter alias</param> /// <param name="metaData">Meta data</param> /// <returns>A syntax tree node representing the table-valued function</returns> public virtual WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, string dumbNode, GraphMetaData metaData) { var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; var edgeColIdentifier = edgeIdentifiers.Last(); var edgeColName = edgeColIdentifier.Value; var bindNodeTableTuple = WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName); HashSet <string> nodeSet; if (!metaData.NodeViewMapping.TryGetValue( WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) { nodeSet = null; } if (IsEdgeView && IsReversedEdge) { var sinkNodeTableTuple = WNamedTableReference.SchemaNameToTuple(SinkNode.NodeTableObjectName); var index = edgeColName.IndexOf(sinkNodeTableTuple.Item2, StringComparison.OrdinalIgnoreCase); index += sinkNodeTableTuple.Item2.Length; var originalEdgeViewName = edgeColName.Substring(index + 1, edgeColName.Length - "Reversed".Length - index - 1); edgeColName = bindNodeTableTuple.Item2 + "_" + originalEdgeViewName + "Reversed"; } NodeColumns columnInfo = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)][ edgeColName]; EdgeInfo edgeInfo = columnInfo.EdgeInfo; List <Tuple <string, string> > edgeTuples = edgeInfo.EdgeColumns; var parameters = ConstructEdgeTvfParameters(nodeAlias, dumbNode, nodeSet, edgeTuples); var decoderFunction = new Identifier { Value = edgeInfo.EdgeUdfPrefix + "_Decoder", }; return(new WSchemaObjectFunctionTableReference { SchemaObject = new WSchemaObjectName( new Identifier { Value = "dbo" }, decoderFunction), Parameters = parameters, Alias = new Identifier { Value = EdgeAlias, } }); }
/// <summary> /// Converts the edge to the table-valued function /// </summary> /// <param name="nodeAlias">Source node alias</param> /// <param name="metaData">Meta data</param> /// <returns>A syntax tree node representing the table-valued function</returns> public virtual WSchemaObjectFunctionTableReference ToSchemaObjectFunction(string nodeAlias, GraphMetaData metaData) { var edgeIdentifiers = EdgeColumn.MultiPartIdentifier.Identifiers; var edgeColIdentifier = edgeIdentifiers.Last(); HashSet <string> nodeSet; if (!metaData.NodeViewMapping.TryGetValue( WNamedTableReference.SchemaNameToTuple(SourceNode.NodeTableObjectName), out nodeSet)) { nodeSet = null; } EdgeInfo edgeInfo = metaData.ColumnsOfNodeTables[WNamedTableReference.SchemaNameToTuple(BindNodeTableObjName)][ edgeColIdentifier.Value].EdgeInfo; List <Tuple <string, string> > edgeTuples = edgeInfo.EdgeColumns; var parameters = ConstructEdgeTvfParameters(nodeAlias, nodeSet, edgeTuples); var decoderFunction = new Identifier { Value = BindNodeTableObjName.SchemaIdentifier.Value + '_' + BindNodeTableObjName.BaseIdentifier.Value + '_' + EdgeColumn.MultiPartIdentifier.Identifiers.Last().Value + '_' + "Decoder" }; return(new WSchemaObjectFunctionTableReference { SchemaObject = new WSchemaObjectName( new Identifier { Value = "dbo" }, decoderFunction), Parameters = parameters, Alias = new Identifier { Value = EdgeAlias, } }); }
/// <summary> /// Imports nodes and edges data into GraphView. /// Runs the following command to enable minimal logging, /// which will highly enhance the performance of bulk loading: /// USE master; ALTER DATABASE database_name SET RECOVERY BULK_LOGGED; /// </summary> /// <param name="nodesFileName"> The list of node file name(s)</param> /// <param name="edgesFileName"> the list of edge file name(s)</param> /// <param name="directory"> The directory of the node and edge data files</param> /// <param name="skipScanLabel"> True, notifies GraphView that every node file has only one label and /// every edge file has only one type. This will improve the performance of importing.</param> /// <param name="fieldTerminator"> The field terminator of data files</param> /// <param name="byDefaultType"> The default data type.</param> public void Import(IList<string> nodesFileName, IList<string> edgesFileName, string directory, bool skipScanLabel = false, string fieldTerminator = ",", string byDefaultType = "string") { if (!string.IsNullOrEmpty(directory)) { if (Directory.Exists(directory)) { nodesFileName = nodesFileName.Select(x => directory + "\\" + x).ToList(); edgesFileName = edgesFileName.Select(x => directory + "\\" + x).ToList(); } else { throw new BulkInsertNodeException(String.Format("The directory {0} does not exist.", directory)); } } if (FileInfo.TypeDict.ContainsKey(byDefaultType.ToLower())) { byDefaultType = FileInfo.TypeDict[byDefaultType.ToLower()]; } else { throw new BulkInsertNodeException("The type by default is not supported. The type supported includes:\n" + "int,long,float,double,boolean,byt,short,char,string\n"); } FileInfo.FieldTerminator = fieldTerminator; FileInfo.RowTerminator = "\r\n"; FileInfo.ByDefaultType = byDefaultType; FileInfo.SkipScanLabel = skipScanLabel; //Collects file header's information var nodeFileToInfo = new Dictionary<string, NodeFileInfo>(); foreach (var it in nodesFileName) { if (!File.Exists(it)) { throw new BulkInsertNodeException(String.Format("The file {0} does not exist.", it)); } else { var temp = new NodeFileInfo(it); temp.getHeader(); temp.ParseHeader(); nodeFileToInfo[it] = temp; } } var edgeFileToInfo = new Dictionary<string, EdgeFileInfo>(); foreach (var it in edgesFileName) { if (!File.Exists(it)) { throw new BulkInsertEdgeException(String.Format("The file {0} does not exist.", it)); } else { var temp = new EdgeFileInfo(it); temp.getHeader(); temp.ParseHeader(); edgeFileToInfo[it] = temp; } } var nameSpaceToNodeTableSet = new Dictionary<string, HashSet<string>>(); //Generates node table's information var nodeTableToInfo = new Dictionary<string, NodeInfo>(); foreach (var it in nodeFileToInfo) { NodeFileInfo nodeFile = it.Value; foreach (var iterator in nodeFile.Labels) { NodeInfo temp; if (nodeTableToInfo.ContainsKey(iterator)) { temp = nodeTableToInfo[iterator]; } else { temp = new NodeInfo(); } //Assigns properties foreach (var VARIABLE in nodeFile.ColumnToType) { if (!temp.AddProperty(VARIABLE.Key, VARIABLE.Value)) { throw new BulkInsertNodeException( String.Format( "The label \"{0}\" contains column \"{1}\" in different types in two different file", iterator, VARIABLE.Key)); } } //Assigns user id var userid = Tuple.Create(nodeFile.UserId.ToLower(), byDefaultType.ToLower()); if (temp.UserId != null && !(userid.Item1 == temp.UserId.Item1 || userid.Item2 == temp.UserId.Item2)) { throw new BulkInsertNodeException(String.Format("The label \"{0}\" contains two differenct ids in two node files", iterator)); } temp.UserId = userid; temp.tableName = iterator; nodeTableToInfo[iterator] = temp; //Updates name space dictionary if (!nameSpaceToNodeTableSet.ContainsKey(nodeFile.NameSpace)) { nameSpaceToNodeTableSet[nodeFile.NameSpace] = new HashSet<string>(); } HashSet<string> nodeTableSet = nameSpaceToNodeTableSet[nodeFile.NameSpace]; if (!nodeTableSet.Contains(iterator)) { nodeTableSet.Add(iterator); } } } //Generates edge file's information foreach (var it in edgeFileToInfo) { EdgeFileInfo edgeFile = it.Value; HashSet<string> startNodeTable = nameSpaceToNodeTableSet[edgeFile.StartNameSpace]; HashSet<string> endNodeTable = nameSpaceToNodeTableSet[edgeFile.EndNameSpace]; var edge = new EdgeInfo(); if (endNodeTable.Count > 2) { throw new BulkInsertEdgeException("One edge cannot refer to two different node tables"); } else if (endNodeTable.Count < 1) { throw new BulkInsertEdgeException( string.Format("Cannot find the namespace \"{0}\" in node files", edgeFile.EndNameSpace)); } foreach (var VARIABLE in endNodeTable) { edgeFile.sinkTable = edge.Sink = VARIABLE; } foreach (var VARIABLE in edgeFile.ColumnToType) { if (!edge.AddAtrribute(VARIABLE.Key, VARIABLE.Value)) { throw new BulkInsertEdgeException( string.Format("The Edge data file \"{0}\" contains two attributes of same name.", it.Key)); } } foreach (var iterator in edgeFile.Labels) { foreach (var VARIABLE in startNodeTable) { if (!nodeTableToInfo[VARIABLE].AddEdge(iterator, edge)) { throw new BulkInsertEdgeException( string.Format("There exists edge type \"{0}\" conflicts on node table \"{1}\" ", iterator, VARIABLE)); } } } } var transaction = Conn.BeginTransaction(); var command = Conn.CreateCommand(); command.Transaction = transaction; command.CommandTimeout = 0; try { //Creates node table foreach (var pair in nodeTableToInfo) { CreateNodeTable(pair.Value.ToString(), transaction); const string dropConstrain = @" ALTER TABLE {0} DROP CONSTRAINT {1}"; string constrainName = "dbo" + pair.Value.tableName + "_PK_GlobalNodeId"; command.CommandText = string.Format(dropConstrain, pair.Value.tableName, constrainName); command.ExecuteNonQuery(); string indexName = "dbo" + pair.Value.tableName + "_UQ_" + pair.Value.UserId.Item1; command.CommandText = string.Format(dropConstrain, pair.Value.tableName, indexName); command.ExecuteNonQuery(); } //Bulk inserts nodes foreach (var pair in nodeFileToInfo) { var nodeFile = pair.Value; //Bulk insert var dataColumnName = new List<string>(nodeFile.FileHeader.Count); var columnDataType = new List<string>(nodeFile.FileHeader.Count); using (var it = nodeFile.ColumnToType.GetEnumerator()) { for (int i = 0; i < nodeFile.FileHeader.Count; i++) { if (i == nodeFile.UserIdOffset) { dataColumnName.Add(nodeFile.UserId); columnDataType.Add(convertSqlType(byDefaultType)); } else if (i == nodeFile.LabelOffset) { dataColumnName.Add("label"); columnDataType.Add(convertSqlType("nvarchar(4000)")); } else { if (it.MoveNext()) { dataColumnName.Add(it.Current.Key); columnDataType.Add(convertSqlType(it.Current.Value)); } } } } foreach (var it in nodeFile.Labels) { var tableNameWithSchema = "dbo." + it; using (var sqlBulkCopy = new SqlBulkCopy(Conn, SqlBulkCopyOptions.TableLock, transaction)) { sqlBulkCopy.BulkCopyTimeout = 0; using ( var reader = skipScanLabel ? new BulkInsertFileDataReader(nodeFile.FileName, fieldTerminator, "\r\n", dataColumnName, columnDataType, true) : new BulkInsertFileDataReader(nodeFile.FileName, fieldTerminator, "\r\n", dataColumnName, columnDataType, true, nodeFile.LabelOffset, it)) { foreach (var variable in dataColumnName) { if (variable != "label") { sqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(variable, variable)); } } sqlBulkCopy.DestinationTableName = tableNameWithSchema; sqlBulkCopy.WriteToServer(reader); } } } } //Rebuilds cluster index on node table foreach (var pair in nodeTableToInfo) { const string createPrimaryKey = @" ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY (GlobalNodeId)"; string constrainName = "dbo" + pair.Value.tableName + "_PK_GlobalNodeId"; command.CommandText = string.Format(createPrimaryKey, pair.Value.tableName, constrainName); command.ExecuteNonQuery(); const string dropIndex = @" ALTER TABLE {0} ADD CONSTRAINT {1} UNIQUE ({2})"; string indexName = "dbo" + pair.Value.tableName + "_UQ_" + pair.Value.UserId.Item1; command.CommandText = string.Format(dropIndex, pair.Value.tableName, indexName, pair.Value.UserId.Item1); command.ExecuteNonQuery(); } //Bulk inserts edges foreach (var pair in edgeFileToInfo) { var edgeFile = pair.Value; var dataColumnName = new List<string>(edgeFile.FileHeader.Count); var columnDataType = new List<string>(edgeFile.FileHeader.Count); using (var it = edgeFile.ColumnToType.GetEnumerator()) { for (int i = 0; i < edgeFile.FileHeader.Count; i++) { if (i == edgeFile.StartIdOffset) { dataColumnName.Add("startid"); columnDataType.Add(convertSqlType(byDefaultType)); } else if (i == edgeFile.EndIdOffset) { dataColumnName.Add("endid"); columnDataType.Add(convertSqlType(byDefaultType)); } if (i == edgeFile.LabelOffset) { dataColumnName.Add("type"); columnDataType.Add(convertSqlType(byDefaultType)); } else { if (it.MoveNext()) { dataColumnName.Add(it.Current.Key); columnDataType.Add(convertSqlType(it.Current.Value)); } } } } HashSet<string> startNodeTable = nameSpaceToNodeTableSet[edgeFile.StartNameSpace]; foreach (var edgeColumnName in edgeFile.Labels) { //Create temp table for bulk inserting edge data var randomTempTableName = "dbo." + edgeColumnName + edgeFile.sinkTable + "_" + RandomString(); var attributes = string.Join(",\n", edgeFile.ColumnToType.Select(x => x.Key + " " + x.Value)); const string createTempTable = @" Create table {0} ( startid {1}, endid {1}, {2} )"; command.CommandText = string.Format(createTempTable, randomTempTableName, byDefaultType, attributes); command.ExecuteNonQuery(); //Bulk inset using (var sqlBulkCopy = new SqlBulkCopy(Conn, SqlBulkCopyOptions.TableLock, transaction)) { sqlBulkCopy.BulkCopyTimeout = 0; using ( var reader = skipScanLabel ? new BulkInsertFileDataReader(edgeFile.FileName, fieldTerminator, "\r\n", dataColumnName, columnDataType, true) : new BulkInsertFileDataReader(edgeFile.FileName, fieldTerminator, "\r\n", dataColumnName, columnDataType, true, edgeFile.LabelOffset, edgeColumnName)) { foreach (var it in dataColumnName) { if (it != "type") { sqlBulkCopy.ColumnMappings.Add(it, it); } } sqlBulkCopy.DestinationTableName = randomTempTableName; sqlBulkCopy.WriteToServer(reader); } } //Creates clustered index on sink node in temp table string clusteredIndexName = "sinkIndex_" + RandomString(); const string createClusteredIndex = @" create clustered index [{0}] on {1}([endid])"; command.Parameters.Clear(); command.CommandText = string.Format(createClusteredIndex, clusteredIndexName, randomTempTableName); command.ExecuteNonQuery(); foreach (var sourceTableName in startNodeTable) { //Updates database string aggregeteFunctionName = "dbo_" + sourceTableName + '_' + edgeColumnName + '_' + "Encoder"; var tempStringForVariable = string.Join(", ", edgeFile.ColumnToType.Select(x => x.Key)); if (!string.IsNullOrEmpty(tempStringForVariable)) { tempStringForVariable = "," + tempStringForVariable; } string aggregateFunction = aggregeteFunctionName + "([sinkTable].[GlobalNodeId]" + tempStringForVariable + ")"; const string updateEdgeData = @" Select [{0}].globalnodeid, [GraphView_InsertEdgeInternalTable].binary, [GraphView_InsertEdgeInternalTable].sinkCount into #ParallelOptimalTempTable From ( Select tempTable.[{2}] source, [{3}].{4} as binary, count([sinkTable].[GlobalNodeId]) as sinkCount From {5} tempTable Join [{3}].[{6}] sinkTable On sinkTable.[{7}] = tempTable.[{8}] Group by tempTable.[{2}] ) as [GraphView_InsertEdgeInternalTable], [{3}].[{0}] Where [{0}].[{9}] = [GraphView_InsertEdgeInternalTable].source; UPDATE [{3}].[{0}] SET {1} .WRITE(temp.[binary], null, null), {1}OutDegree += sinkCount from #ParallelOptimalTempTable temp where temp.globalnodeid = [{0}].globalnodeid; drop table #ParallelOptimalTempTable;"; command.Parameters.Clear(); var sinkTableId = nodeTableToInfo[edgeFile.sinkTable].UserId.Item1; var sourceTableId = nodeTableToInfo[sourceTableName].UserId.Item1; command.CommandText = string.Format(updateEdgeData, sourceTableName, edgeColumnName, "startid", "dbo", aggregateFunction, randomTempTableName, edgeFile.sinkTable, sinkTableId, "endid", sourceTableId); command.ExecuteNonQuery(); const string updateReversedEdgeData = @" UPDATE [{3}].[{0}] SET [InDegree] += sourceCount From ( Select tempTable.[{1}] as Sink, count(*) as sourceCount From {2} tempTable Join [{5}] On [{5}].[{6}] = tempTable.[{7}] Group by tempTable.[{1}] ) as [GraphView_InsertEdgeInternalTable] Where [GraphView_InsertEdgeInternalTable].Sink = [{0}].[{4}]"; command.CommandText = string.Format(updateReversedEdgeData, edgeFile.sinkTable, "endid", randomTempTableName, "dbo", sinkTableId, sourceTableName, sourceTableId, "startid"); command.ExecuteNonQuery(); //Drops temp table const string dropTempTable = @" drop table {0}"; command.CommandText = string.Format(dropTempTable, randomTempTableName); command.ExecuteNonQuery(); } } } transaction.Commit(); } catch (Exception error) { transaction.Rollback(); throw new BulkInsertNodeException(error.Message); } }
public bool AddEdge(string edgeName, EdgeInfo info) { if (EdgesToInfo.ContainsKey(edgeName)) { if (EdgesToInfo[edgeName] != info) { return false; } } EdgesToInfo[edgeName] = info; return true; }
/// <summary> /// Retrieve the metadata /// </summary> /// <param name="conn"></param> private void Init() { _graphMetaData = new GraphMetaData(); var columnsOfNodeTables = _graphMetaData.ColumnsOfNodeTables; var nodeViewMapping = _graphMetaData.NodeViewMapping; var revEdgeOrderDict = _graphMetaData.ReversedEdgeOrder; using (var command = Tx.Connection.CreateCommand()) { command.Transaction = Tx; command.CommandText = string.Format( @" SELECT [TableSchema] as [Schema], [TableName] as [Name1], [ColumnName] as [Name2], [ColumnRole] as [Role], [Reference] as [Name3], [HasReversedEdge] as [HasRevEdge], [IsReversedEdge] as [IsRevEdge], [EdgeUdfPrefix] as [UdfPrefix], null as [EdgeViewTable], null as [ColumnId] FROM [{0}] UNION ALL SELECT [TableSchema] as [Schema], [TableName] as [Name1], [ColumnName] as [Name2], -1 as [Role], [AttributeName] as [Name3], 0, 0, null, null, [AttributeId] FROM [{1}] UNION ALL SELECT [NV].[TableSchema] as [Schema], [NV].[TableName] as [Name1], [NT].[TableName] as [Name2], -2 as [Role], null as [Name3], 0, 0, null, null, null FROM [{2}] as [NV_NT_Mapping] JOIN [{3}] as [NV] ON NV_NT_Mapping.NodeViewTableId = NV.TableId JOIN [{3}] as [NT] ON NV_NT_Mapping.TableId = NT.TableId UNION ALL SELECT [EV].[TableSchema] as [Schema], [EV].[ColumnName] as [Name1], [ED].[ColumnName]as [Name2], -3 as [Role], [ED].[TableName] as [Name3], 0, 0, null, [EV].[TableName] as [EdgeViewTable], [ED].[ColumnId] as [ColumnId] FROM [{4}] as [EV_ED_Mapping] JOIN [{0}] as [EV] ON [EV_ED_Mapping].[NodeViewColumnId] = [EV].[ColumnId] and [EV].[ColumnRole] = 3 JOIN [{0}] as [ED] ON [EV_ED_Mapping].[ColumnId] = [ED].[ColumnId] ORDER BY [ColumnId]", GraphViewConnection.MetadataTables[1], GraphViewConnection.MetadataTables[2], GraphViewConnection.MetadataTables[7], GraphViewConnection.MetadataTables[0], GraphViewConnection.MetadataTables[5]); var revEdgeOrder = 0; using (var reader = command.ExecuteReader()) { while (reader.Read()) { int tag = (int) reader["Role"]; string schema = reader["Schema"].ToString().ToLower(CultureInfo.CurrentCulture); string name1 = reader["Name1"].ToString().ToLower(CultureInfo.CurrentCulture); string name2 = reader["Name2"].ToString().ToLower(CultureInfo.CurrentCulture); bool hasRevEdge = reader["HasRevEdge"].ToString().Equals("1"); bool isRevEdge = reader["IsRevEdge"].ToString().Equals("1"); string udfPrefix = reader["UdfPrefix"].ToString().ToLower(CultureInfo.CurrentCulture); // Retrieve columns of node tables var tableTuple = new Tuple<string, string>(schema, name1); if (tag >= 0) { Dictionary<string, NodeColumns> columnDict; if (!columnsOfNodeTables.TryGetValue(tableTuple, out columnDict)) { columnDict = new Dictionary<string, NodeColumns>(StringComparer.OrdinalIgnoreCase); columnsOfNodeTables.Add(tableTuple, columnDict); } var role = (WNodeTableColumnRole) tag; EdgeInfo edgeInfo = null; // Edge column if (role == WNodeTableColumnRole.Edge || role == WNodeTableColumnRole.EdgeView) { edgeInfo = new EdgeInfo { ColumnAttributes = new List<string>(), SinkNodes = role == WNodeTableColumnRole.Edge ? new HashSet<string>(StringComparer.OrdinalIgnoreCase) { reader["Name3"].ToString().ToLower(CultureInfo.CurrentCulture) } : new HashSet<string>(StringComparer.OrdinalIgnoreCase), HasReversedEdge = hasRevEdge, IsReversedEdge = isRevEdge, EdgeUdfPrefix = udfPrefix, }; if (role == WNodeTableColumnRole.Edge) { var tableSchema = reader["Schema"].ToString(); var tableName = reader["Name1"].ToString(); var edgeName = reader["Name2"].ToString(); var refTableName = reader["Name3"].ToString(); var revEdgeName = (tableName + "_" + edgeName + "Reversed").ToLower(); var tuple = new Tuple<string, string>(tableSchema.ToLower(), refTableName.ToLower()); if (!revEdgeOrderDict.ContainsKey(tuple)) revEdgeOrderDict[tuple] = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); revEdgeOrderDict[tuple][revEdgeName] = revEdgeOrder; ++revEdgeOrder; } } columnDict.Add(name2, new NodeColumns { EdgeInfo = edgeInfo, Role = role, }); } // Retrieve edge attributes else if (tag == -1) { var columnDict = columnsOfNodeTables[tableTuple]; columnDict[name2].EdgeInfo.ColumnAttributes.Add(reader["Name3"].ToString() .ToLower(CultureInfo.CurrentCulture)); } // Retrieve node view mapping else if (tag == -2) { HashSet<string> nodeTableSet; if (!nodeViewMapping.TryGetValue(tableTuple, out nodeTableSet)) { nodeTableSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); nodeViewMapping.Add(tableTuple, nodeTableSet); } nodeTableSet.Add(name2); } // Retrieve edge view mapping else if (tag == -3) { string edgeViewSourceTableName = reader["EdgeViewTable"].ToString().ToLower(CultureInfo.CurrentCulture); string sourceTableName = reader["Name3"].ToString().ToLower(CultureInfo.CurrentCulture); string sinkTableName = columnsOfNodeTables[new Tuple<string, string>(schema, sourceTableName)][name2] .EdgeInfo.SinkNodes.First(); var edgeViewInfo = columnsOfNodeTables[new Tuple<string, string>(schema, edgeViewSourceTableName)][ name1].EdgeInfo; if (!edgeViewInfo.SinkNodes.Contains(sourceTableName)) edgeViewInfo.SinkNodes.Add(sinkTableName); if (edgeViewInfo.EdgeColumns == null) edgeViewInfo.EdgeColumns = new List<Tuple<string, string>>(); edgeViewInfo.EdgeColumns.Add(new Tuple<string, string>(sourceTableName, name2)); } } // sort reversed edgeViews' EdgeColumn according to the order of their corresponding original edges' column Ids // to match the rule of edgeView's decoder function parameters placing order foreach (var it in columnsOfNodeTables) { foreach (var edge in it.Value) { if (edge.Value.Role == WNodeTableColumnRole.EdgeView && edge.Value.EdgeInfo.IsReversedEdge) { var edgeInfo = edge.Value.EdgeInfo; edgeInfo.EdgeColumns = edgeInfo.EdgeColumns.OrderBy( x => revEdgeOrderDict[new Tuple<string, string>("dbo", x.Item1)][x.Item2]) .ToList(); } } } } } }
/// <summary> /// Retrieve the metadata /// </summary> /// <param name="conn"></param> private void Init() { _graphMetaData = new GraphMetaData(); var columnsOfNodeTables = _graphMetaData.ColumnsOfNodeTables; var nodeViewMapping = _graphMetaData.NodeViewMapping; using (var command = Tx.Connection.CreateCommand()) { command.Transaction = Tx; command.CommandText = string.Format( @" SELECT [TableSchema] as [Schema], [TableName] as [Name1], [ColumnName] as [Name2], [ColumnRole] as [Role], [Reference] as [Name3], null as [EdgeViewTable], null as [ColumnId] FROM [{0}] UNION ALL SELECT [TableSchema] as [Schema], [TableName] as [Name1], [ColumnName] as [Name2], -1 as [Role], [AttributeName] as [Name3], null, [AttributeId] FROM [{1}] UNION ALL SELECT [NV].[TableSchema] as [Schema], [NV].[TableName] as [Name1], [NT].[TableName] as [Name2], -2 as [Role], null as [Name3], null, null FROM [{2}] as [NV_NT_Mapping] JOIN [{3}] as [NV] ON NV_NT_Mapping.NodeViewTableId = NV.TableId JOIN [{3}] as [NT] ON NV_NT_Mapping.TableId = NT.TableId UNION ALL SELECT [EV].[TableSchema] as [Schema], [EV].[ColumnName] as [Name1], [ED].[ColumnName]as [Name2], -3 as [Role], [ED].[TableName] as [Name3], [EV].[TableName] as [EdgeViewTable], [ED].[ColumnId] as [ColumnId] FROM [{4}] as [EV_ED_Mapping] JOIN [{0}] as [EV] ON [EV_ED_Mapping].[NodeViewColumnId] = [EV].[ColumnId] and [EV].[ColumnRole] = 3 JOIN [{0}] as [ED] ON [EV_ED_Mapping].[ColumnId] = [ED].[ColumnId] ORDER BY [ColumnId]", GraphViewConnection.MetadataTables[1], GraphViewConnection.MetadataTables[2], GraphViewConnection.MetadataTables[7], GraphViewConnection.MetadataTables[0], GraphViewConnection.MetadataTables[5]); using (var reader = command.ExecuteReader()) { while (reader.Read()) { int tag = (int) reader["Role"]; string schema = reader["Schema"].ToString().ToLower(CultureInfo.CurrentCulture); string name1 = reader["Name1"].ToString().ToLower(CultureInfo.CurrentCulture); string name2 = reader["Name2"].ToString().ToLower(CultureInfo.CurrentCulture); // Retrieve columns of node tables var tableTuple = new Tuple<string, string>(schema, name1); if (tag >= 0) { Dictionary<string, NodeColumns> columnDict; if (!columnsOfNodeTables.TryGetValue(tableTuple, out columnDict)) { columnDict = new Dictionary<string, NodeColumns>(StringComparer.OrdinalIgnoreCase); columnsOfNodeTables.Add(tableTuple, columnDict); } var role = (WNodeTableColumnRole) tag; EdgeInfo edgeInfo = null; // Edge column if (role == WNodeTableColumnRole.Edge || role == WNodeTableColumnRole.EdgeView) { edgeInfo = new EdgeInfo { ColumnAttributes = new List<string>(), SinkNodes = role == WNodeTableColumnRole.Edge ? new HashSet<string>(StringComparer.OrdinalIgnoreCase) { reader["Name3"].ToString().ToLower(CultureInfo.CurrentCulture) } : new HashSet<string>(StringComparer.OrdinalIgnoreCase), }; } columnDict.Add(name2, new NodeColumns { EdgeInfo = edgeInfo, Role = role, }); } // Retrieve edge attributes else if (tag == -1) { var columnDict = columnsOfNodeTables[tableTuple]; columnDict[name2].EdgeInfo.ColumnAttributes.Add(reader["Name3"].ToString() .ToLower(CultureInfo.CurrentCulture)); } // Retrieve node view mapping else if (tag == -2) { HashSet<string> nodeTableSet; if (!nodeViewMapping.TryGetValue(tableTuple, out nodeTableSet)) { nodeTableSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); nodeViewMapping.Add(tableTuple, nodeTableSet); } nodeTableSet.Add(name2); } // Retrieve edge view mapping else if (tag == -3) { string edgeViewSourceTableName = reader["EdgeViewTable"].ToString().ToLower(CultureInfo.CurrentCulture); string sourceTableName = reader["Name3"].ToString().ToLower(CultureInfo.CurrentCulture); string sinkTableName = columnsOfNodeTables[new Tuple<string, string>(schema, sourceTableName)][name2] .EdgeInfo.SinkNodes.First(); var edgeViewInfo = columnsOfNodeTables[new Tuple<string, string>(schema, edgeViewSourceTableName)][ name1].EdgeInfo; if (!edgeViewInfo.SinkNodes.Contains(sourceTableName)) edgeViewInfo.SinkNodes.Add(sinkTableName); if (edgeViewInfo.EdgeColumns == null) edgeViewInfo.EdgeColumns = new List<Tuple<string, string>>(); edgeViewInfo.EdgeColumns.Add(new Tuple<string, string>(sourceTableName, name2)); } } } } }