Skip to content

Commit 4ede05e

Browse files
Hadi FadlallahHadi Fadlallah
Hadi Fadlallah
authored and
Hadi Fadlallah
committed
Add functions to migrate indexes and constraints
1 parent f110b6f commit 4ede05e

File tree

5 files changed

+179
-5
lines changed

5 files changed

+179
-5
lines changed

SQLToNeo4j/Edge.cs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public Edge(string id, string label, string from, string fromID, string to, stri
2424
Properties = properties;
2525
else
2626
Properties = new Dictionary<string, object>();
27+
2728
}
2829

2930
}

SQLToNeo4j/Neo4jWriter.cs

+17-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ public void ImportNodes(List<Node> nodes)
2121
string cypher =
2222
"(" + nd.Label + "_" + nd.ID.ToString() + ":" + nd.Label + " $prop)";
2323
client.Cypher.Create(cypher).WithParam("prop", nd.Properties).ExecuteWithoutResultsAsync().Wait(); ;
24+
2425
}
2526
}
26-
2727
public void ImportEdges(List<Edge> edges)
2828
{
2929
foreach (Edge edg in edges)
@@ -39,10 +39,24 @@ public void ImportEdges(List<Edge> edges)
3939
.Where(edg.FromNode.ToLower() + "1.node_id = $id1")
4040
.AndWhere(edg.ToNode.ToLower() + "2.node_id = $id2")
4141
.Create(cypher)
42-
.WithParams(param).ExecuteWithoutResultsAsync().Wait(); ;
42+
.WithParams(param).ExecuteWithoutResultsAsync().Wait();
4343
}
4444
}
45-
45+
public void ImportIndexes(List<string> indexes)
46+
{
47+
foreach(string cmd in indexes)
48+
client.Cypher.Create(cmd).ExecuteWithoutResultsAsync().Wait();
49+
}
50+
public void ImportFullTextIndexes(List<string> ftindexes)
51+
{
52+
foreach (string cmd in ftindexes)
53+
client.Cypher.Call(cmd).ExecuteWithoutResultsAsync().Wait();
54+
}
55+
public void ImportConstraints(List<string> constraints)
56+
{
57+
foreach (string cmd in constraints)
58+
client.Cypher.Create(cmd).ExecuteWithoutResultsAsync().Wait();
59+
}
4660
public void Dispose()
4761
{
4862
client.Dispose();

SQLToNeo4j/SQLCommands.cs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace SQLToNeo4j
6+
{
7+
public static class SQLcommands
8+
{
9+
public static string GetIndexes = "SELECT 'INDEX ' + ind.name + ' FOR (t:' + t.name +') ON (' + STRING_AGG('t.' + Col.name,',') + ')'" +
10+
" FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id INNER JOIN sys.tables t ON ind.object_id = t.object_id" +
11+
" WHERE ind.type = 2 and (t.is_node = 1 or t.is_edge = 1) and col.name not like 'graph_id_%' and t.name <> 'sysdiagrams'" +
12+
" GROUP BY ind.name, t.name";
13+
public static string GetFullTextIndexes = "SELECT 'db.index.fulltext.' + case t.is_node when 1 then 'createNodeIndex(\"N_' else 'createRelationshipIndex(\"Rel_' end + cat.name + '\", [' + STRING_AGG('\"' + t.name + '\"',', ') + '], [' + STRING_AGG('\"' + col.name + '\"',', ') + '])' " +
14+
" FROM sys.fulltext_catalogs cat INNER JOIN sys.fulltext_indexes ind ON cat.fulltext_catalog_id = ind.fulltext_catalog_id INNER JOIN sys.fulltext_index_columns ic ON ind.object_id = ic.object_id " +
15+
" INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id INNER JOIN sys.tables t ON ind.object_id = t.object_id " +
16+
" WHERE (t.is_node = 1 or t.is_edge = 1) and col.name not like 'graph_id_%' and t.name <> 'sysdiagrams' " +
17+
" GROUP BY t.is_node, cat.name";
18+
public static string GetUniqueConstraints = "SELECT 'CONSTRAINT UC_' + ind.name + ' ON (n:' + t.name + ') ASSERT n.' + col.name + ' IS UNIQUE' " +
19+
" FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id " +
20+
" INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id " +
21+
" INNER JOIN sys.tables t ON ind.object_id = t.object_id " +
22+
" WHERE ind.type = 2 and (t.is_node = 1 or t.is_edge = 1) and col.name not like 'graph_id_%' and t.name <> 'sysdiagrams' " +
23+
" and (ind.is_unique = 1 or ind.is_unique_constraint = 1) " +
24+
" GROUP BY ind.name,t.name,col.name" +
25+
" HAVING COUNT(*) = 1";
26+
public static string GetExistenceConstraints = "select CASE WHEN t.is_node = 1 then 'CONSTRAINT ' + t.name + '_' + col.name + '_exist ON (n:' + t.name + ') ASSERT EXISTS (n.' + col.name + ')' ELSE 'CONSTRAINT ' + t.name + '_' + col.name + '_exist ON ()-\"[\"R:' + t.name + '\"]\"-() ASSERT EXISTS (R.' + col.name + ')' END " +
27+
" FROM sys.columns col INNER JOIN sys.tables t ON col.object_id = t.object_id " +
28+
" where col.is_nullable = 0 and col.graph_type IS NULL and (t.is_edge = 1 or t.is_node = 1) " +
29+
" and not exists (select * from sys.index_columns ic inner join sys.indexes ind on ic.index_id = ind.index_id and ind.object_id = ic.object_id " +
30+
" where ind.is_primary_key = 1 and ic.column_id = col.column_id and t.object_id = ind.object_id and t.is_node = 1)";
31+
public static string GetNodeKeyConstraints = "select 'CONSTRAINT NKC_' + t.name + ' ON (n:' + t.name + ') ASSERT (' + STRING_AGG('n.' + col.name,',') + ') IS NODE KEY' " +
32+
" FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id INNER JOIN sys.tables t ON ind.object_id = t.object_id " +
33+
" INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id " +
34+
" where graph_type IS NULL -- Ignore graph system columns and t.is_node = 1 and ind.is_primary_key = 1 " +
35+
" GROUP BY t.name";
36+
37+
38+
}
39+
}

SQLToNeo4j/SQLReader.cs

+110
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@ public class SQLReader : IDisposable
1010
{
1111
public List<Node> Nodes { get; set; }
1212
public List<Edge> Edges { get; set; }
13+
public List<string> Indexes { get; set; }
14+
public List<string> FullTextIndexes { get; set; }
15+
public List<string> UniqueConstraints { get; set; }
16+
public List<string> ExistenceConstraints { get; set; }
17+
public List<string> NodeKeyConstraints { get; set; }
18+
1319
public string ConnectionString { get; set; }
1420

1521
public SQLReader(string connection)
1622
{
1723
ConnectionString = connection;
24+
Indexes = new List<string>();
25+
FullTextIndexes = new List<string>();
26+
UniqueConstraints = new List<string>();
27+
ExistenceConstraints = new List<string>();
28+
NodeKeyConstraints = new List<string>();
1829
}
1930
public void GetNodes()
2031
{
@@ -153,7 +164,106 @@ public void GetEdges()
153164
}
154165

155166
}
167+
public void GetIndexes()
168+
{
169+
//initialize connection
170+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
171+
{
172+
sqlcon.Open();
173+
//retrieving Indexes
174+
175+
using (SqlCommand sqlIndexes = new SqlCommand(SQLcommands.GetIndexes, sqlcon))
176+
{
177+
SqlDataReader indexreader;
178+
indexreader = sqlIndexes.ExecuteReader();
179+
180+
//get index create statements
181+
while (indexreader.Read())
182+
Indexes.Add(indexreader[0].ToString());
183+
184+
}
185+
}
186+
}
187+
public void GetFullTextIndexes()
188+
{
189+
//initialize connection
190+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
191+
{
192+
sqlcon.Open();
193+
//retrieving Indexes
194+
195+
using (SqlCommand sqlFullTextIndexes = new SqlCommand(SQLcommands.GetFullTextIndexes, sqlcon))
196+
{
197+
SqlDataReader indexreader;
198+
indexreader = sqlFullTextIndexes.ExecuteReader();
199+
200+
//get index create statements
201+
while (indexreader.Read())
202+
FullTextIndexes.Add(indexreader[0].ToString());
203+
204+
}
205+
}
206+
}
207+
public void GetUniqueConstraints()
208+
{
209+
//initialize connection
210+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
211+
{
212+
sqlcon.Open();
213+
//retrieving Indexes
156214

215+
using (SqlCommand sqlUniqueConstraints = new SqlCommand(SQLcommands.GetUniqueConstraints, sqlcon))
216+
{
217+
SqlDataReader uqcreader;
218+
uqcreader = sqlUniqueConstraints.ExecuteReader();
219+
220+
//get index create statements
221+
while (uqcreader.Read())
222+
UniqueConstraints.Add(uqcreader[0].ToString());
223+
224+
}
225+
}
226+
}
227+
public void GetExistenceConstraints()
228+
{
229+
//initialize connection
230+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
231+
{
232+
sqlcon.Open();
233+
//retrieving Indexes
234+
235+
using (SqlCommand sqlExistenceConstraints = new SqlCommand(SQLcommands.GetExistenceConstraints, sqlcon))
236+
{
237+
SqlDataReader excreader;
238+
excreader = sqlExistenceConstraints.ExecuteReader();
239+
240+
//get index create statements
241+
while (excreader.Read())
242+
ExistenceConstraints.Add(excreader[0].ToString());
243+
244+
}
245+
}
246+
}
247+
public void GetNodeKeyConstraints()
248+
{
249+
//initialize connection
250+
using (SqlConnection sqlcon = new SqlConnection(ConnectionString))
251+
{
252+
sqlcon.Open();
253+
//retrieving Indexes
254+
255+
using (SqlCommand sqlNodeKeyConstraints = new SqlCommand(SQLcommands.GetNodeKeyConstraints, sqlcon))
256+
{
257+
SqlDataReader nkcreader;
258+
nkcreader = sqlNodeKeyConstraints.ExecuteReader();
259+
260+
//get index create statements
261+
while (nkcreader.Read())
262+
NodeKeyConstraints.Add(nkcreader[0].ToString());
263+
264+
}
265+
}
266+
}
157267
public void Dispose()
158268
{
159269
Nodes = null;

SQLToNeo4jDemo/Program.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,25 @@ class Program
66
{
77
static void Main(string[] args)
88
{
9-
using (SQLReader reader = new SQLReader("Server=<machine name>\\<instance name>;Database=GraphPL;Trusted_Connection=yes;"))
9+
using (SQLReader reader = new SQLReader("Server=DESKTOP-KCL006K\\DATASERVER;Database=GraphPL;Trusted_Connection=yes;"))
1010
{
1111
reader.GetNodes();
1212
reader.GetEdges();
13+
reader.GetIndexes();
14+
reader.GetFullTextIndexes();
15+
reader.GetUniqueConstraints();
16+
//reader.GetExistenceConstraints(); -- available only in enterprise edition
17+
//reader.GetNodeKeyConstraints(); -- available only in enterprise edition
1318

14-
using (Neo4jWriter importer = new Neo4jWriter(new Uri("http://<user>:<password>@localhost:7474")))
19+
using (Neo4jWriter importer = new Neo4jWriter(new Uri("http://neo4j:123@localhost:7474")))
1520
{
1621
importer.ImportNodes(reader.Nodes);
1722
importer.ImportEdges(reader.Edges);
23+
importer.ImportIndexes(reader.Indexes);
24+
importer.ImportFullTextIndexes(reader.FullTextIndexes);
25+
importer.ImportConstraints(reader.UniqueConstraints);
26+
//importer.ImportConstraints(reader.ExistenceConstraints); -- available only in enterprise edition
27+
//importer.ImportConstraints(reader.NodeKeyConstraints); -- available only in enterprise edition
1828
}
1929
}
2030
}

0 commit comments

Comments
 (0)