@@ -38,7 +38,7 @@ class ImportExecutionPlanIT {
3838
3939 @ Test
4040 void exposes_execution_plan () throws Exception {
41- try (InputStream stream = this .getClass ().getResourceAsStream ("/e2e/admin-import/spec .yaml" )) {
41+ try (InputStream stream = this .getClass ().getResourceAsStream ("/e2e/execution-plan/northwind .yaml" )) {
4242 assertThat (stream ).isNotNull ();
4343 try (var reader = new InputStreamReader (stream )) {
4444 var pipeline = ImportPipeline .of (ImportSpecificationDeserializer .deserialize (reader ));
@@ -58,7 +58,7 @@ void exposes_execution_plan() throws Exception {
5858 new JdbcSource (
5959 "products_in_categories" ,
6060 "northwind" ,
61- "SELECT p.productname AS productname, c.categoryname AS categoryname FROM products p NATURAL JOIN categories c ORDER BY p.productname ASC " ));
61+ "SELECT p.productname AS productname, c.categoryname AS categoryname FROM products p NATURAL JOIN categories c ORDER BY p.productname ASC" ));
6262 var categorySource = new SourceStep (new JdbcSource (
6363 "categories" ,
6464 "northwind" ,
@@ -78,7 +78,7 @@ void exposes_execution_plan() throws Exception {
7878 new PropertyMapping ("productname" , "name" , null ),
7979 new PropertyMapping ("unitprice" , "unitPrice" , null )),
8080 nodeSchema (new NodeKeyConstraint (
81- "name_key_constraint " , "Product" , List .of ("name" ), null ))),
81+ "product_name_key_constraint " , "Product" , List .of ("name" ), null ))),
8282 Set .of (productSource ));
8383 var categoryNodeStep = new NodeTargetStep (
8484 new NodeTarget (
@@ -93,7 +93,7 @@ void exposes_execution_plan() throws Exception {
9393 new PropertyMapping ("categoryname" , "name" , null ),
9494 new PropertyMapping ("description" , "description" , null )),
9595 nodeSchema (new NodeKeyConstraint (
96- "name_key_constraint " , "Category" , List .of ("name" ), null ))),
96+ "category_name_key_constraint " , "Category" , List .of ("name" ), null ))),
9797 Set .of (categorySource ));
9898 assertThat (stages .get (1 )).isEqualTo (new ImportStepStage (Set .of (productNodeStep , categoryNodeStep )));
9999 assertThat (stages .get (2 ))
@@ -118,6 +118,93 @@ void exposes_execution_plan() throws Exception {
118118 }
119119 }
120120
121+ @ Test
122+ void exposes_execution_plan_with_relationships_sharing_common_nodes () throws Exception {
123+ try (InputStream stream =
124+ this .getClass ().getResourceAsStream ("/e2e/execution-plan/northwind-rels-with-common-nodes.yaml" )) {
125+ assertThat (stream ).isNotNull ();
126+ try (var reader = new InputStreamReader (stream )) {
127+ var pipeline = ImportPipeline .of (ImportSpecificationDeserializer .deserialize (reader ));
128+
129+ var executionPlan = pipeline .executionPlan ();
130+
131+ var groups = executionPlan .getGroups ();
132+ assertThat (groups ).hasSize (1 );
133+ var group = groups .getFirst ();
134+ var stages = group .getStages ();
135+ assertThat (stages ).hasSize (3 );
136+ assertThat (stages .get (0 ).getSteps ()).hasSize (5 );
137+ var customerSource = new SourceStep (
138+ new JdbcSource (
139+ "customers" ,
140+ "northwind" ,
141+ "SELECT customer_id, first_name, last_name FROM customers ORDER BY first_name ASC, last_name ASC" ));
142+ var customerNodeStep = new NodeTargetStep (
143+ new NodeTarget (
144+ true ,
145+ "customer_nodes" ,
146+ "customers" ,
147+ null ,
148+ null ,
149+ (ObjectNode ) null ,
150+ List .of ("Customer" ),
151+ List .of (
152+ new PropertyMapping ("customer_id" , "id" , null ),
153+ new PropertyMapping ("first_name" , "first_name" , null ),
154+ new PropertyMapping ("last_name" , "last_name" , null )),
155+ nodeSchema (new NodeKeyConstraint (
156+ "customer_id_key_constraint" , "Customer" , List .of ("id" ), null ))),
157+ Set .of (customerSource ));
158+ assertThat (stages .get (1 ).getSteps ()).hasSize (3 ).contains (customerNodeStep );
159+ var customerBoughtProductSource = new SourceStep (
160+ new JdbcSource (
161+ "customers_bought_products" ,
162+ "northwind" ,
163+ "SELECT p.productname AS productname, c.customer_id AS customer_id FROM products p NATURAL JOIN customers c ORDER BY p.productname ASC" ));
164+ var productNodeStep = new NodeTargetStep (
165+ new NodeTarget (
166+ true ,
167+ "product_nodes" ,
168+ "products" ,
169+ null ,
170+ null ,
171+ (ObjectNode ) null ,
172+ List .of ("Product" ),
173+ List .of (
174+ new PropertyMapping ("productname" , "name" , null ),
175+ new PropertyMapping ("unitprice" , "unitPrice" , null )),
176+ nodeSchema (new NodeKeyConstraint (
177+ "product_name_key_constraint" , "Product" , List .of ("name" ), null ))),
178+ Set .of (new SourceStep (new JdbcSource (
179+ "products" ,
180+ "northwind" ,
181+ "SELECT productname, unitprice FROM products ORDER BY productname ASC" ))));
182+ assertThat (stages .get (2 ).getSteps ())
183+ .hasSize (2 )
184+ // FIXME: overlapping rels should be spread across different stages
185+ // TODO: also add a test where rels overlap but don't use the same labels for the nodes
186+ // (possible with custom key mappings)
187+ .contains (new RelationshipTargetStep (
188+ new RelationshipTarget (
189+ true ,
190+ "customers_bought_products_relationships" ,
191+ "customers_bought_products" ,
192+ null ,
193+ "BOUGHT" ,
194+ null ,
195+ null ,
196+ null ,
197+ new NodeReference ("customer_nodes" ),
198+ new NodeReference ("product_nodes" ),
199+ null ,
200+ null ),
201+ customerNodeStep ,
202+ productNodeStep ,
203+ Set .of (customerBoughtProductSource , productNodeStep , customerNodeStep )));
204+ }
205+ }
206+ }
207+
121208 private NodeSchema nodeSchema (NodeKeyConstraint key ) {
122209 return new NodeSchema (null , List .of (key ), null , null , null , null , null , null , null );
123210 }
0 commit comments