Skip to content

Commit 7dd67bc

Browse files
committed
fix(cypher): apply distinct before return limits
Signed-off-by: Pcristin <xxxokzxxx@protonmail.com>
1 parent b637e33 commit 7dd67bc

2 files changed

Lines changed: 52 additions & 3 deletions

File tree

src/cypher/cypher.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4115,7 +4115,7 @@ static void build_return_columns(result_builder_t *rb, cbm_return_clause_t *ret)
41154115
static void execute_return_simple(cbm_return_clause_t *ret, binding_t *bindings, int bind_count,
41164116
int max_rows, result_builder_t *rb) {
41174117
int proj_cap = max_rows;
4118-
if (ret->limit > 0 && !ret->order_by && ret->skip <= 0) {
4118+
if (ret->limit > 0 && !ret->distinct && !ret->order_by && ret->skip <= 0) {
41194119
proj_cap = ret->limit;
41204120
}
41214121
for (int bi = 0; bi < bind_count && rb->row_count < proj_cap; bi++) {
@@ -4397,11 +4397,11 @@ static void execute_return_clause(cbm_query_t *q, cbm_return_clause_t *ret, bind
43974397
}
43984398
}
43994399

4400-
rb_apply_order_by(rb, ret);
4401-
rb_apply_skip_limit(rb, ret->skip, ret->limit >= 0 ? ret->limit : max_rows);
44024400
if (ret->distinct) {
44034401
rb_apply_distinct(rb);
44044402
}
4403+
rb_apply_order_by(rb, ret);
4404+
rb_apply_skip_limit(rb, ret->skip, ret->limit >= 0 ? ret->limit : max_rows);
44054405
}
44064406

44074407
static int execute_single(cbm_store_t *store, cbm_query_t *q, const char *project, int max_rows,

tests/test_cypher.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,6 +2528,52 @@ TEST(cypher_issue237_distinct_order_limit) {
25282528
PASS();
25292529
}
25302530

2531+
/* #873: duplicate projected rows must be deduped before ORDER BY + LIMIT */
2532+
TEST(cypher_issue873_distinct_order_limit_dedupes_before_limit) {
2533+
cbm_store_t *s = setup_cypher_store();
2534+
cbm_cypher_result_t r = {0};
2535+
int rc = cbm_cypher_execute(
2536+
s, "MATCH (n) RETURN DISTINCT n.label AS label ORDER BY label LIMIT 2", "test", 0, &r);
2537+
ASSERT_EQ(rc, 0);
2538+
ASSERT_NULL(r.error);
2539+
ASSERT_EQ(r.row_count, 2);
2540+
ASSERT_STR_EQ(r.rows[0][0], "Function");
2541+
ASSERT_STR_EQ(r.rows[1][0], "Module");
2542+
cbm_cypher_result_free(&r);
2543+
cbm_store_close(s);
2544+
PASS();
2545+
}
2546+
2547+
/* #873: early LIMIT must not truncate rows before DISTINCT for simple RETURN */
2548+
TEST(cypher_issue873_distinct_limit_dedupes_before_limit) {
2549+
cbm_store_t *s = setup_cypher_store();
2550+
cbm_cypher_result_t r = {0};
2551+
int rc = cbm_cypher_execute(
2552+
s, "MATCH (n) RETURN DISTINCT n.label AS label LIMIT 2", "test", 0, &r);
2553+
ASSERT_EQ(rc, 0);
2554+
ASSERT_NULL(r.error);
2555+
ASSERT_EQ(r.row_count, 2);
2556+
cbm_cypher_result_free(&r);
2557+
cbm_store_close(s);
2558+
PASS();
2559+
}
2560+
2561+
/* #873: SKIP is applied after DISTINCT and ORDER BY, not before dedupe */
2562+
TEST(cypher_issue873_distinct_order_skip_limit_dedupes_before_skip) {
2563+
cbm_store_t *s = setup_cypher_store();
2564+
cbm_cypher_result_t r = {0};
2565+
int rc = cbm_cypher_execute(
2566+
s, "MATCH (n) RETURN DISTINCT n.label AS label ORDER BY label SKIP 1 LIMIT 1", "test",
2567+
0, &r);
2568+
ASSERT_EQ(rc, 0);
2569+
ASSERT_NULL(r.error);
2570+
ASSERT_EQ(r.row_count, 1);
2571+
ASSERT_STR_EQ(r.rows[0][0], "Module");
2572+
cbm_cypher_result_free(&r);
2573+
cbm_store_close(s);
2574+
PASS();
2575+
}
2576+
25312577
/* #252: toInteger() */
25322578
TEST(cypher_issue252_tointeger) {
25332579
cbm_store_t *s = setup_cypher_store();
@@ -2669,6 +2715,9 @@ SUITE(cypher) {
26692715
RUN_TEST(cypher_exec_match_all_functions);
26702716
RUN_TEST(cypher_issue240_labels_function);
26712717
RUN_TEST(cypher_issue237_distinct_order_limit);
2718+
RUN_TEST(cypher_issue873_distinct_order_limit_dedupes_before_limit);
2719+
RUN_TEST(cypher_issue873_distinct_limit_dedupes_before_limit);
2720+
RUN_TEST(cypher_issue873_distinct_order_skip_limit_dedupes_before_skip);
26722721
RUN_TEST(cypher_issue252_tointeger);
26732722
RUN_TEST(cypher_issue305_count_star_alias);
26742723
RUN_TEST(cypher_exec_where_eq);

0 commit comments

Comments
 (0)