Skip to content

Commit 417cd1c

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

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
@@ -4105,7 +4105,7 @@ static void build_return_columns(result_builder_t *rb, cbm_return_clause_t *ret)
41054105
static void execute_return_simple(cbm_return_clause_t *ret, binding_t *bindings, int bind_count,
41064106
int max_rows, result_builder_t *rb) {
41074107
int proj_cap = max_rows;
4108-
if (ret->limit > 0 && !ret->order_by && ret->skip <= 0) {
4108+
if (ret->limit > 0 && !ret->distinct && !ret->order_by && ret->skip <= 0) {
41094109
proj_cap = ret->limit;
41104110
}
41114111
for (int bi = 0; bi < bind_count && rb->row_count < proj_cap; bi++) {
@@ -4387,11 +4387,11 @@ static void execute_return_clause(cbm_query_t *q, cbm_return_clause_t *ret, bind
43874387
}
43884388
}
43894389

4390-
rb_apply_order_by(rb, ret);
4391-
rb_apply_skip_limit(rb, ret->skip, ret->limit >= 0 ? ret->limit : max_rows);
43924390
if (ret->distinct) {
43934391
rb_apply_distinct(rb);
43944392
}
4393+
rb_apply_order_by(rb, ret);
4394+
rb_apply_skip_limit(rb, ret->skip, ret->limit >= 0 ? ret->limit : max_rows);
43954395
}
43964396

43974397
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
@@ -2524,6 +2524,52 @@ TEST(cypher_issue237_distinct_order_limit) {
25242524
PASS();
25252525
}
25262526

2527+
/* #873: duplicate projected rows must be deduped before ORDER BY + LIMIT */
2528+
TEST(cypher_issue873_distinct_order_limit_dedupes_before_limit) {
2529+
cbm_store_t *s = setup_cypher_store();
2530+
cbm_cypher_result_t r = {0};
2531+
int rc = cbm_cypher_execute(
2532+
s, "MATCH (n) RETURN DISTINCT n.label AS label ORDER BY label LIMIT 2", "test", 0, &r);
2533+
ASSERT_EQ(rc, 0);
2534+
ASSERT_NULL(r.error);
2535+
ASSERT_EQ(r.row_count, 2);
2536+
ASSERT_STR_EQ(r.rows[0][0], "Function");
2537+
ASSERT_STR_EQ(r.rows[1][0], "Module");
2538+
cbm_cypher_result_free(&r);
2539+
cbm_store_close(s);
2540+
PASS();
2541+
}
2542+
2543+
/* #873: early LIMIT must not truncate rows before DISTINCT for simple RETURN */
2544+
TEST(cypher_issue873_distinct_limit_dedupes_before_limit) {
2545+
cbm_store_t *s = setup_cypher_store();
2546+
cbm_cypher_result_t r = {0};
2547+
int rc = cbm_cypher_execute(
2548+
s, "MATCH (n) RETURN DISTINCT n.label AS label LIMIT 2", "test", 0, &r);
2549+
ASSERT_EQ(rc, 0);
2550+
ASSERT_NULL(r.error);
2551+
ASSERT_EQ(r.row_count, 2);
2552+
cbm_cypher_result_free(&r);
2553+
cbm_store_close(s);
2554+
PASS();
2555+
}
2556+
2557+
/* #873: SKIP is applied after DISTINCT and ORDER BY, not before dedupe */
2558+
TEST(cypher_issue873_distinct_order_skip_limit_dedupes_before_skip) {
2559+
cbm_store_t *s = setup_cypher_store();
2560+
cbm_cypher_result_t r = {0};
2561+
int rc = cbm_cypher_execute(
2562+
s, "MATCH (n) RETURN DISTINCT n.label AS label ORDER BY label SKIP 1 LIMIT 1", "test",
2563+
0, &r);
2564+
ASSERT_EQ(rc, 0);
2565+
ASSERT_NULL(r.error);
2566+
ASSERT_EQ(r.row_count, 1);
2567+
ASSERT_STR_EQ(r.rows[0][0], "Module");
2568+
cbm_cypher_result_free(&r);
2569+
cbm_store_close(s);
2570+
PASS();
2571+
}
2572+
25272573
/* #252: toInteger() */
25282574
TEST(cypher_issue252_tointeger) {
25292575
cbm_store_t *s = setup_cypher_store();
@@ -2624,6 +2670,9 @@ SUITE(cypher) {
26242670
RUN_TEST(cypher_exec_match_all_functions);
26252671
RUN_TEST(cypher_issue240_labels_function);
26262672
RUN_TEST(cypher_issue237_distinct_order_limit);
2673+
RUN_TEST(cypher_issue873_distinct_order_limit_dedupes_before_limit);
2674+
RUN_TEST(cypher_issue873_distinct_limit_dedupes_before_limit);
2675+
RUN_TEST(cypher_issue873_distinct_order_skip_limit_dedupes_before_skip);
26272676
RUN_TEST(cypher_issue252_tointeger);
26282677
RUN_TEST(cypher_issue305_count_star_alias);
26292678
RUN_TEST(cypher_exec_where_eq);

0 commit comments

Comments
 (0)