• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "ejdb2_internal.h"
2 
3 static_assert(IW_VNUMBUFSZ <= JBNUMBUF_SIZE, "IW_VNUMBUFSZ <= JBNUMBUF_SIZE");
4 
_jbi_consume_eq(struct _JBEXEC * ctx,JQVAL * jqval,JB_SCAN_CONSUMER consumer)5 static iwrc _jbi_consume_eq(struct _JBEXEC *ctx, JQVAL *jqval, JB_SCAN_CONSUMER consumer) {
6   size_t sz;
7   uint64_t id;
8   int64_t step;
9   bool matched;
10   struct _JBMIDX *midx = &ctx->midx;
11   char numbuf[JBNUMBUF_SIZE];
12   IWKV_val key;
13 
14   jbi_jqval_fill_ikey(midx->idx, jqval, &key, numbuf);
15   if (!key.size) {
16     return consumer(ctx, 0, 0, 0, 0, 0);
17   }
18   iwrc rc = iwkv_get_copy(midx->idx->idb, &key, numbuf, sizeof(numbuf), &sz);
19   if (rc) {
20     if (rc == IWKV_ERROR_NOTFOUND) {
21       return consumer(ctx, 0, 0, 0, 0, 0);
22     } else {
23       return rc;
24     }
25   }
26   IW_READVNUMBUF64_2(numbuf, id);
27   rc = consumer(ctx, 0, id, &step, &matched, 0);
28   return consumer(ctx, 0, 0, 0, 0, rc);
29 }
30 
_jbi_consume_in_node(struct _JBEXEC * ctx,JQVAL * jqval,JB_SCAN_CONSUMER consumer)31 static iwrc _jbi_consume_in_node(struct _JBEXEC *ctx, JQVAL *jqval, JB_SCAN_CONSUMER consumer) {
32   JQVAL jqv;
33   size_t sz;
34   uint64_t id;
35   bool matched;
36   char numbuf[JBNUMBUF_SIZE];
37 
38   iwrc rc = 0;
39   int64_t step = 1;
40   IWKV_val key;
41   struct _JBMIDX *midx = &ctx->midx;
42   JBL_NODE nv = jqval->vnode->child;
43 
44   if (!nv) {
45     return consumer(ctx, 0, 0, 0, 0, 0);
46   }
47   do {
48     jql_node_to_jqval(nv, &jqv);
49     jbi_jqval_fill_ikey(midx->idx, &jqv, &key, numbuf);
50     if (!key.size) {
51       continue;
52     }
53     rc = iwkv_get_copy(midx->idx->idb, &key, numbuf, sizeof(numbuf), &sz);
54     if (rc) {
55       if (rc == IWKV_ERROR_NOTFOUND) {
56         rc = 0;
57         continue;
58       } else {
59         goto finish;
60       }
61     }
62     if (step > 0) {
63       --step;
64     } else if (step < 0) {
65       ++step;
66     }
67     if (!step) {
68       IW_READVNUMBUF64_2(numbuf, id);
69       step = 1;
70       rc = consumer(ctx, 0, id, &step, &matched, 0);
71       RCGO(rc, finish);
72     }
73   } while (step && (step > 0 ? (nv = nv->next) : (nv = nv->prev)));
74 
75 finish:
76   return consumer(ctx, 0, 0, 0, 0, rc);
77 }
78 
_jbi_consume_scan(struct _JBEXEC * ctx,JQVAL * jqval,JB_SCAN_CONSUMER consumer)79 static iwrc _jbi_consume_scan(struct _JBEXEC *ctx, JQVAL *jqval, JB_SCAN_CONSUMER consumer) {
80   size_t sz;
81   IWKV_cursor cur;
82   char numbuf[JBNUMBUF_SIZE];
83 
84   int64_t step = 1;
85   struct _JBMIDX *midx = &ctx->midx;
86   JBIDX idx = midx->idx;
87   jqp_op_t expr1_op = midx->expr1->op->value;
88 
89   IWKV_val key;
90   jbi_jqval_fill_ikey(idx, jqval, &key, numbuf);
91 
92   iwrc rc = iwkv_cursor_open(idx->idb, &cur, midx->cursor_init, &key);
93   if ((rc == IWKV_ERROR_NOTFOUND) && ((expr1_op == JQP_OP_LT) || (expr1_op == JQP_OP_LTE))) {
94     iwkv_cursor_close(&cur);
95     midx->cursor_init = IWKV_CURSOR_BEFORE_FIRST;
96     midx->cursor_step = IWKV_CURSOR_NEXT;
97     rc = iwkv_cursor_open(idx->idb, &cur, midx->cursor_init, 0);
98     RCGO(rc, finish);
99     if (!midx->expr2) { // Fail fast
100       midx->expr2 = midx->expr1;
101     }
102   } else if (rc) {
103     goto finish;
104   }
105 
106   IWKV_cursor_op cursor_reverse_step = (midx->cursor_step == IWKV_CURSOR_NEXT)
107                                        ? IWKV_CURSOR_PREV : IWKV_CURSOR_NEXT;
108 
109   if (midx->cursor_init < IWKV_CURSOR_NEXT) { // IWKV_CURSOR_BEFORE_FIRST || IWKV_CURSOR_AFTER_LAST
110     rc = iwkv_cursor_to(cur, midx->cursor_step);
111     RCGO(rc, finish);
112   }
113   do {
114     if (step > 0) {
115       --step;
116     } else if (step < 0) {
117       ++step;
118     }
119     if (!step) {
120       int64_t id;
121       bool matched = false;
122       rc = iwkv_cursor_copy_val(cur, &numbuf, IW_VNUMBUFSZ, &sz);
123       RCGO(rc, finish);
124       if (sz > IW_VNUMBUFSZ) {
125         rc = IWKV_ERROR_CORRUPTED;
126         iwlog_ecode_error3(rc);
127         break;
128       }
129       IW_READVNUMBUF64_2(numbuf, id);
130       if (  midx->expr2
131          && !midx->expr2->prematched
132          && !jbi_node_expr_matched(ctx->ux->q->aux, midx->idx, cur, midx->expr2, &rc)) {
133         break;
134       }
135       if (  (expr1_op == JQP_OP_PREFIX)
136          && !jbi_node_expr_matched(ctx->ux->q->aux, midx->idx, cur, midx->expr1, &rc)) {
137         break;
138       }
139       RCGO(rc, finish);
140 
141       step = 1;
142       rc = consumer(ctx, 0, id, &step, &matched, 0);
143       RCGO(rc, finish);
144       if (!midx->expr1->prematched && matched && (expr1_op != JQP_OP_PREFIX)) {
145         // Further scan will always match the main index expression
146         midx->expr1->prematched = true;
147       }
148     }
149   } while (step && !(rc = iwkv_cursor_to(cur, step > 0 ? midx->cursor_step : cursor_reverse_step)));
150 
151 finish:
152   if (rc == IWKV_ERROR_NOTFOUND) {
153     rc = 0;
154   }
155   if (cur) {
156     iwkv_cursor_close(&cur);
157   }
158   return consumer(ctx, 0, 0, 0, 0, rc);
159 }
160 
_jbi_consume_noxpr_scan(struct _JBEXEC * ctx,JB_SCAN_CONSUMER consumer)161 iwrc _jbi_consume_noxpr_scan(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer) {
162   size_t sz;
163   IWKV_cursor cur;
164   char numbuf[JBNUMBUF_SIZE];
165   int64_t step = 1;
166   struct _JBMIDX *midx = &ctx->midx;
167   IWKV_cursor_op cursor_reverse_step = (midx->cursor_step == IWKV_CURSOR_NEXT)
168                                        ? IWKV_CURSOR_PREV : IWKV_CURSOR_NEXT;
169 
170   iwrc rc = iwkv_cursor_open(midx->idx->idb, &cur, midx->cursor_init, 0);
171   RCGO(rc, finish);
172   if (midx->cursor_init < IWKV_CURSOR_NEXT) { // IWKV_CURSOR_BEFORE_FIRST || IWKV_CURSOR_AFTER_LAST
173     rc = iwkv_cursor_to(cur, midx->cursor_step);
174     RCGO(rc, finish);
175   }
176   do {
177     if (step > 0) {
178       --step;
179     } else if (step < 0) {
180       ++step;
181     }
182     if (!step) {
183       int64_t id;
184       bool matched;
185       rc = iwkv_cursor_copy_val(cur, &numbuf, IW_VNUMBUFSZ, &sz);
186       RCGO(rc, finish);
187       if (sz > IW_VNUMBUFSZ) {
188         rc = IWKV_ERROR_CORRUPTED;
189         iwlog_ecode_error3(rc);
190         break;
191       }
192       IW_READVNUMBUF64_2(numbuf, id);
193       RCGO(rc, finish);
194       step = 1;
195       rc = consumer(ctx, 0, id, &step, &matched, 0);
196       RCGO(rc, finish);
197     }
198   } while (step && !(rc = iwkv_cursor_to(cur, step > 0 ? midx->cursor_step : cursor_reverse_step)));
199 
200 finish:
201   if (rc == IWKV_ERROR_NOTFOUND) {
202     rc = 0;
203   }
204   if (cur) {
205     iwkv_cursor_close(&cur);
206   }
207   return consumer(ctx, 0, 0, 0, 0, rc);
208 }
209 
jbi_uniq_scanner(struct _JBEXEC * ctx,JB_SCAN_CONSUMER consumer)210 iwrc jbi_uniq_scanner(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer) {
211   iwrc rc;
212   struct _JBMIDX *midx = &ctx->midx;
213   if (!midx->expr1) {
214     return _jbi_consume_noxpr_scan(ctx, consumer);
215   }
216   JQP_QUERY *qp = ctx->ux->q->qp;
217   JQVAL *jqval = jql_unit_to_jqval(qp->aux, midx->expr1->right, &rc);
218   RCRET(rc);
219   switch (midx->expr1->op->value) {
220     case JQP_OP_EQ:
221       return _jbi_consume_eq(ctx, jqval, consumer);
222     case JQP_OP_IN:
223       if (jqval->type == JQVAL_JBLNODE) {
224         return _jbi_consume_in_node(ctx, jqval, consumer);
225       } else {
226         iwlog_ecode_error3(IW_ERROR_ASSERTION);
227         return IW_ERROR_ASSERTION;
228       }
229       break;
230     default:
231       break;
232   }
233   if ((midx->expr1->op->value == JQP_OP_GT) && (jqval->type == JQVAL_I64)) {
234     JQVAL mjqv;
235     memcpy(&mjqv, jqval, sizeof(*jqval));
236     mjqv.vi64 = mjqv.vi64 + 1; // Because for index scan we use `IWKV_CURSOR_GE`
237     return _jbi_consume_scan(ctx, &mjqv, consumer);
238   } else {
239     return _jbi_consume_scan(ctx, jqval, consumer);
240   }
241 }
242