@@ -1917,6 +1917,32 @@ TEST(cypher_exists_has_outgoing_calls) {
19171917 ASSERT_EQ (rc , 0 );
19181918 ASSERT_EQ (r .row_count , 2 );
19191919 cbm_cypher_result_free (& r );
1920+
1921+ rc = cbm_cypher_execute (s ,
1922+ "MATCH (a)-[:CALLS]->(b) WHERE b.name <> \"SubmitOrder\" "
1923+ "RETURN a.name, b.name" ,
1924+ "test" , 0 , & r );
1925+ ASSERT_EQ (rc , 0 );
1926+ ASSERT_EQ (r .row_count , 2 );
1927+ cbm_cypher_result_free (& r );
1928+
1929+ rc = cbm_cypher_execute (s ,
1930+ "MATCH (a)-[:CALLS]->(b) WHERE b.name = \"SubmitOrder\" OR "
1931+ "NOT b.name = \"SubmitOrder\" RETURN count(*)" ,
1932+ "test" , 0 , & r );
1933+ ASSERT_EQ (rc , 0 );
1934+ ASSERT_EQ (r .row_count , 1 );
1935+ ASSERT_STR_EQ (r .rows [0 ][0 ], "3" );
1936+ cbm_cypher_result_free (& r );
1937+
1938+ rc = cbm_cypher_execute (s ,
1939+ "MATCH (a)-[:CALLS]->(b) WITH a, b WHERE NOT b.name = "
1940+ "\"SubmitOrder\" RETURN a.name, b.name" ,
1941+ "test" , 0 , & r );
1942+ ASSERT_EQ (rc , 0 );
1943+ ASSERT_EQ (r .row_count , 2 );
1944+ cbm_cypher_result_free (& r );
1945+
19201946 cbm_store_close (s );
19211947 PASS ();
19221948}
@@ -3378,6 +3404,86 @@ TEST(cypher_exec_where_mixed_alias_xor) {
33783404 PASS ();
33793405}
33803406
3407+ TEST (cypher_exec_where_not_target_node ) {
3408+ cbm_store_t * s = setup_cypher_store ();
3409+ cbm_cypher_result_t r = {0 };
3410+ int rc = cbm_cypher_execute (s ,
3411+ "MATCH (a)-[:CALLS]->(b) WHERE NOT b.name = \"SubmitOrder\" "
3412+ "RETURN a.name, b.name" ,
3413+ "test" , 0 , & r );
3414+ ASSERT_EQ (rc , 0 );
3415+ ASSERT_EQ (r .row_count , 2 );
3416+ cbm_cypher_result_free (& r );
3417+ cbm_store_close (s );
3418+ PASS ();
3419+ }
3420+
3421+ TEST (cypher_exec_where_not_target_relationship ) {
3422+ cbm_store_t * s = setup_cypher_multi_edge_store ();
3423+ cbm_cypher_result_t r = {0 };
3424+ int rc = cbm_cypher_execute (s ,
3425+ "MATCH (a)-[r:HTTP_CALLS]->(b) WHERE NOT r.url_path = "
3426+ "\"/health\" RETURN r.url_path" ,
3427+ "testproj" , 0 , & r );
3428+ ASSERT_EQ (rc , 0 );
3429+ ASSERT_EQ (r .row_count , 1 );
3430+ ASSERT_STR_EQ (r .rows [0 ][0 ], "/api/orders" );
3431+ cbm_cypher_result_free (& r );
3432+ cbm_store_close (s );
3433+ PASS ();
3434+ }
3435+
3436+ TEST (cypher_exec_where_not_source_node ) {
3437+ cbm_store_t * s = setup_cypher_store ();
3438+ cbm_cypher_result_t r = {0 };
3439+ int rc = cbm_cypher_execute (s ,
3440+ "MATCH (a)-[:CALLS]->(b) WHERE NOT a.name = "
3441+ "\"HandleOrder\" RETURN a.name, b.name" ,
3442+ "test" , 0 , & r );
3443+ ASSERT_EQ (rc , 0 );
3444+ ASSERT_EQ (r .row_count , 1 );
3445+ ASSERT_STR_EQ (r .rows [0 ][0 ], "ValidateOrder" );
3446+ cbm_cypher_result_free (& r );
3447+ cbm_store_close (s );
3448+ PASS ();
3449+ }
3450+
3451+ TEST (cypher_exec_where_not_target_node_count ) {
3452+ cbm_store_t * s = setup_cypher_store ();
3453+ cbm_cypher_result_t r = {0 };
3454+ int rc = cbm_cypher_execute (s ,
3455+ "MATCH (a)-[:CALLS]->(b) WHERE NOT b.name = "
3456+ "\"SubmitOrder\" RETURN count(*)" ,
3457+ "test" , 0 , & r );
3458+ ASSERT_EQ (rc , 0 );
3459+ ASSERT_EQ (r .row_count , 1 );
3460+ ASSERT_STR_EQ (r .rows [0 ][0 ], "2" );
3461+ cbm_cypher_result_free (& r );
3462+ cbm_store_close (s );
3463+ PASS ();
3464+ }
3465+
3466+ /* The early WHERE pass must wait for every alias a condition reads. A function
3467+ * condition is filed under its first argument's alias, so in
3468+ * coalesce(a.no_such_prop, b.name) the target b hid behind the bound a: the
3469+ * seed row read coalesce(NULL, <unbound b>) as a definite mismatch and pruned
3470+ * every row before CALLS expansion, while the same predicate after WITH was
3471+ * right. */
3472+ TEST (cypher_exec_where_func_arg_on_unbound_target ) {
3473+ cbm_store_t * s = setup_cypher_store ();
3474+ cbm_cypher_result_t r = {0 };
3475+ int rc = cbm_cypher_execute (s ,
3476+ "MATCH (a)-[:CALLS]->(b) WHERE coalesce(a.no_such_prop, b.name) = "
3477+ "\"SubmitOrder\" RETURN a.name" ,
3478+ "test" , 0 , & r );
3479+ ASSERT_EQ (rc , 0 );
3480+ ASSERT_EQ (r .row_count , 1 );
3481+ ASSERT_STR_EQ (r .rows [0 ][0 ], "ValidateOrder" );
3482+ cbm_cypher_result_free (& r );
3483+ cbm_store_close (s );
3484+ PASS ();
3485+ }
3486+
33813487TEST (cypher_exec_where_in ) {
33823488 cbm_store_t * s = setup_cypher_store ();
33833489 cbm_cypher_result_t r = {0 };
@@ -6243,6 +6349,11 @@ SUITE(cypher) {
62436349 RUN_TEST (cypher_exec_where_mixed_alias_and );
62446350 RUN_TEST (cypher_exec_where_mixed_alias_or );
62456351 RUN_TEST (cypher_exec_where_mixed_alias_xor );
6352+ RUN_TEST (cypher_exec_where_not_target_node );
6353+ RUN_TEST (cypher_exec_where_not_target_relationship );
6354+ RUN_TEST (cypher_exec_where_not_source_node );
6355+ RUN_TEST (cypher_exec_where_not_target_node_count );
6356+ RUN_TEST (cypher_exec_where_func_arg_on_unbound_target );
62466357 RUN_TEST (cypher_exec_where_in );
62476358 RUN_TEST (cypher_exec_where_not_in );
62486359 RUN_TEST (cypher_exec_where_is_null );
0 commit comments