• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "ejdb2_internal.h"
2 
3 static_assert(IW_VNUMBUFSZ <= IWNUMBUF_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[IWNUMBUF_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[IWNUMBUF_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       RCC(rc, finish, consumer(ctx, 0, id, &step, &matched, 0));
71     }
72   } while (step && (step > 0 ? (nv = nv->next) : (nv = nv->prev)));
73 
74 finish:
75   return consumer(ctx, 0, 0, 0, 0, rc);
76 }
77 
_jbi_consume_scan(struct _JBEXEC * ctx,JQVAL * jqval,JB_SCAN_CONSUMER consumer)78 static iwrc _jbi_consume_scan(struct _JBEXEC *ctx, JQVAL *jqval, JB_SCAN_CONSUMER consumer) {
79   size_t sz;
80   IWKV_cursor cur;
81   char numbuf[IWNUMBUF_SIZE];
82 
83   int64_t step = 1;
84   struct _JBMIDX *midx = &ctx->midx;
85   JBIDX idx = midx->idx;
86   jqp_op_t expr1_op = midx->expr1->op->value;
87 
88   IWKV_val key;
89   jbi_jqval_fill_ikey(idx, jqval, &key, numbuf);
90 
91   iwrc rc = iwkv_cursor_open(idx->idb, &cur, midx->cursor_init, &key);
92   if ((rc == IWKV_ERROR_NOTFOUND) && ((expr1_op == JQP_OP_LT) || (expr1_op == JQP_OP_LTE))) {
93     iwkv_cursor_close(&cur);
94     midx->cursor_init = IWKV_CURSOR_BEFORE_FIRST;
95     midx->cursor_step = IWKV_CURSOR_NEXT;
96     RCC(rc, finish, iwkv_cursor_open(idx->idb, &cur, midx->cursor_init, 0));
97     if (!midx->expr2) { // Fail fast
98       midx->expr2 = midx->expr1;
99     }
100   } else if (rc) {
101     goto finish;
102   }
103 
104   IWKV_cursor_op cursor_reverse_step = (midx->cursor_step == IWKV_CURSOR_NEXT)
105                                        ? IWKV_CURSOR_PREV : IWKV_CURSOR_NEXT;
106 
107   if (midx->cursor_init < IWKV_CURSOR_NEXT) { // IWKV_CURSOR_BEFORE_FIRST || IWKV_CURSOR_AFTER_LAST
108     RCC(rc, finish, iwkv_cursor_to(cur, midx->cursor_step));
109   }
110   do {
111     if (step > 0) {
112       --step;
113     } else if (step < 0) {
114       ++step;
115     }
116     if (!step) {
117       int64_t id;
118       bool matched = false;
119       RCC(rc, finish, iwkv_cursor_copy_val(cur, &numbuf, IW_VNUMBUFSZ, &sz));
120       if (sz > IW_VNUMBUFSZ) {
121         rc = IWKV_ERROR_CORRUPTED;
122         iwlog_ecode_error3(rc);
123         break;
124       }
125       IW_READVNUMBUF64_2(numbuf, id);
126       if (  midx->expr2
127          && !midx->expr2->prematched
128          && !jbi_node_expr_matched(ctx->ux->q->aux, midx->idx, cur, midx->expr2, &rc)) {
129         break;
130       }
131       if (  (expr1_op == JQP_OP_PREFIX)
132          && !jbi_node_expr_matched(ctx->ux->q->aux, midx->idx, cur, midx->expr1, &rc)) {
133         break;
134       }
135       RCGO(rc, finish);
136 
137       step = 1;
138       RCC(rc, finish, consumer(ctx, 0, id, &step, &matched, 0));
139       if (!midx->expr1->prematched && matched && (expr1_op != JQP_OP_PREFIX)) {
140         // Further scan will always match the main index expression
141         midx->expr1->prematched = true;
142       }
143     }
144   } while (step && !(rc = iwkv_cursor_to(cur, step > 0 ? midx->cursor_step : cursor_reverse_step)));
145 
146 finish:
147   if (rc == IWKV_ERROR_NOTFOUND) {
148     rc = 0;
149   }
150   if (cur) {
151     iwkv_cursor_close(&cur);
152   }
153   return consumer(ctx, 0, 0, 0, 0, rc);
154 }
155 
_jbi_consume_noxpr_scan(struct _JBEXEC * ctx,JB_SCAN_CONSUMER consumer)156 iwrc _jbi_consume_noxpr_scan(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer) {
157   iwrc rc;
158   size_t sz;
159   IWKV_cursor cur;
160   char numbuf[IWNUMBUF_SIZE];
161   int64_t step = 1;
162   struct _JBMIDX *midx = &ctx->midx;
163   IWKV_cursor_op cursor_reverse_step = (midx->cursor_step == IWKV_CURSOR_NEXT)
164                                        ? IWKV_CURSOR_PREV : IWKV_CURSOR_NEXT;
165 
166   RCC(rc, finish, iwkv_cursor_open(midx->idx->idb, &cur, midx->cursor_init, 0));
167   if (midx->cursor_init < IWKV_CURSOR_NEXT) { // IWKV_CURSOR_BEFORE_FIRST || IWKV_CURSOR_AFTER_LAST
168     RCC(rc, finish, iwkv_cursor_to(cur, midx->cursor_step));
169   }
170   do {
171     if (step > 0) {
172       --step;
173     } else if (step < 0) {
174       ++step;
175     }
176     if (!step) {
177       int64_t id;
178       bool matched;
179       RCC(rc, finish, iwkv_cursor_copy_val(cur, &numbuf, IW_VNUMBUFSZ, &sz));
180       if (sz > IW_VNUMBUFSZ) {
181         rc = IWKV_ERROR_CORRUPTED;
182         iwlog_ecode_error3(rc);
183         break;
184       }
185       IW_READVNUMBUF64_2(numbuf, id);
186       RCGO(rc, finish);
187       step = 1;
188       RCC(rc, finish, consumer(ctx, 0, id, &step, &matched, 0));
189     }
190   } while (step && !(rc = iwkv_cursor_to(cur, step > 0 ? midx->cursor_step : cursor_reverse_step)));
191 
192 finish:
193   if (rc == IWKV_ERROR_NOTFOUND) {
194     rc = 0;
195   }
196   if (cur) {
197     iwkv_cursor_close(&cur);
198   }
199   return consumer(ctx, 0, 0, 0, 0, rc);
200 }
201 
jbi_uniq_scanner(struct _JBEXEC * ctx,JB_SCAN_CONSUMER consumer)202 iwrc jbi_uniq_scanner(struct _JBEXEC *ctx, JB_SCAN_CONSUMER consumer) {
203   iwrc rc;
204   struct _JBMIDX *midx = &ctx->midx;
205   if (!midx->expr1) {
206     return _jbi_consume_noxpr_scan(ctx, consumer);
207   }
208   JQP_QUERY *qp = ctx->ux->q->qp;
209   JQVAL *jqval = jql_unit_to_jqval(qp->aux, midx->expr1->right, &rc);
210   RCRET(rc);
211   switch (midx->expr1->op->value) {
212     case JQP_OP_EQ:
213       return _jbi_consume_eq(ctx, jqval, consumer);
214     case JQP_OP_IN:
215       if (jqval->type == JQVAL_JBLNODE) {
216         return _jbi_consume_in_node(ctx, jqval, consumer);
217       } else {
218         iwlog_ecode_error3(IW_ERROR_ASSERTION);
219         return IW_ERROR_ASSERTION;
220       }
221       break;
222     default:
223       break;
224   }
225   if ((midx->expr1->op->value == JQP_OP_GT) && (jqval->type == JQVAL_I64)) {
226     JQVAL mjqv;
227     memcpy(&mjqv, jqval, sizeof(*jqval));
228     mjqv.vi64 = mjqv.vi64 + 1; // Because for index scan we use `IWKV_CURSOR_GE`
229     return _jbi_consume_scan(ctx, &mjqv, consumer);
230   } else {
231     return _jbi_consume_scan(ctx, jqval, consumer);
232   }
233 }
234