1 // -V::802 2 #pragma once 3 #ifndef JQP_H 4 #define JQP_H 5 6 /************************************************************************************************** 7 * EJDB2 8 * 9 * MIT License 10 * 11 * Copyright (c) 2012-2022 Softmotions Ltd <info@softmotions.com> 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy 14 * of this software and associated documentation files (the "Software"), to deal 15 * in the Software without restriction, including without limitation the rights 16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 * copies of the Software, and to permit persons to whom the Software is 18 * furnished to do so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in all 21 * copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 * SOFTWARE. 30 *************************************************************************************************/ 31 32 #include "jql.h" 33 34 #include <iowow/iwpool.h> 35 #include <iowow/iwxstr.h> 36 37 #include <errno.h> 38 #include <stdbool.h> 39 #include <setjmp.h> 40 41 typedef uint16_t jqp_string_flavours_t; 42 /** Query string parameter placeholder */ 43 #define JQP_STR_PLACEHOLDER ((jqp_string_flavours_t) 0x01U) 44 /** Query filter anchor */ 45 #define JQP_STR_ANCHOR ((jqp_string_flavours_t) 0x02U) 46 /** Projection field **/ 47 #define JQP_STR_PROJFIELD ((jqp_string_flavours_t) 0x04U) 48 /** Projection alias (all) **/ 49 #define JQP_STR_PROJALIAS ((jqp_string_flavours_t) 0x08U) 50 /** String is quoted */ 51 #define JQP_STR_QUOTED ((jqp_string_flavours_t) 0x10U) 52 /** Star (*) string */ 53 #define JQP_STR_STAR ((jqp_string_flavours_t) 0x20U) 54 /** Boolean negation/mode applied to it */ 55 #define JQP_STR_NEGATE ((jqp_string_flavours_t) 0x40U) 56 /** Double star (**) string */ 57 #define JQP_STR_DBL_STAR ((jqp_string_flavours_t) 0x80U) 58 /** Projection JOIN */ 59 #define JQP_STR_PROJOIN ((jqp_string_flavours_t) 0x100U) 60 /** Projection path */ 61 #define JQP_STR_PROJPATH ((jqp_string_flavours_t) 0x200U) 62 63 64 typedef uint8_t jqp_int_flavours_t; 65 #define JQP_INT_SKIP ((jqp_int_flavours_t) 0x01U) 66 #define JQP_INT_LIMIT ((jqp_int_flavours_t) 0x02U) 67 68 typedef enum { 69 JQP_QUERY_TYPE = 1, 70 JQP_EXPR_NODE_TYPE, 71 JQP_FILTER_TYPE, 72 JQP_NODE_TYPE, 73 JQP_EXPR_TYPE, 74 JQP_STRING_TYPE, 75 JQP_INTEGER_TYPE, 76 JQP_DOUBLE_TYPE, 77 JQP_OP_TYPE, 78 JQP_JOIN_TYPE, 79 JQP_PROJECTION_TYPE, 80 JQP_JSON_TYPE, 81 } jqp_unit_t; 82 83 typedef enum { 84 JQP_NODE_FIELD = 1, 85 JQP_NODE_ANY, 86 JQP_NODE_ANYS, 87 JQP_NODE_EXPR, 88 } jqp_node_type_t; 89 90 typedef enum { 91 // Do not reorder members 92 JQP_JOIN_AND = 1, 93 JQP_JOIN_OR, 94 JQP_OP_EQ, 95 JQP_OP_GT, 96 JQP_OP_GTE, 97 JQP_OP_LT, 98 JQP_OP_LTE, 99 JQP_OP_IN, 100 JQP_OP_NI, 101 JQP_OP_RE, 102 JQP_OP_PREFIX, 103 } jqp_op_t; 104 105 struct JQP_AUX; 106 107 typedef union _JQP_UNIT JQPUNIT; 108 109 #define JQP_EXPR_NODE_FLAG_PK 0x01U 110 111 #define JQP_EXPR_NODE_HEAD \ 112 jqp_unit_t type; \ 113 struct JQP_EXPR_NODE *next; \ 114 struct JQP_JOIN *join; \ 115 void *opaque; \ 116 uint8_t flags; 117 118 typedef struct JQP_EXPR_NODE { // Base for JQP_FILTER 119 JQP_EXPR_NODE_HEAD 120 struct JQP_EXPR_NODE *chain; 121 } JQP_EXPR_NODE; 122 123 typedef struct JQP_EXPR_NODE_PK { 124 JQP_EXPR_NODE_HEAD 125 struct JQP_EXPR_NODE *chain; // Not used, plased for JQP_EXPR_NODE compatibility 126 const char *anchor; 127 JQPUNIT *argument; 128 } JQP_EXPR_NODE_PK; 129 130 typedef struct JQP_FILTER { 131 JQP_EXPR_NODE_HEAD 132 const char *anchor; 133 struct JQP_NODE *node; 134 } JQP_FILTER; 135 136 typedef struct JQP_JSON { 137 jqp_unit_t type; 138 struct _JBL_NODE jn; 139 void *opaque; 140 } JQP_JSON; 141 142 typedef struct JQP_NODE { 143 jqp_unit_t type; 144 jqp_node_type_t ntype; 145 struct JQP_NODE *next; 146 JQPUNIT *value; 147 int start; // Used in query matching 148 int end; // Used in query matching 149 } JQP_NODE; 150 151 typedef struct JQP_STRING { 152 jqp_unit_t type; 153 jqp_string_flavours_t flavour; 154 const char *value; 155 struct JQP_STRING *next; 156 struct JQP_STRING *subnext; 157 struct JQP_STRING *placeholder_next; 158 void *opaque; 159 } JQP_STRING; 160 161 typedef struct JQP_INTEGER { 162 jqp_unit_t type; 163 jqp_int_flavours_t flavour; 164 int64_t value; 165 void *opaque; 166 } JQP_INTEGER; 167 168 typedef struct JQP_DOUBLE { 169 jqp_unit_t type; 170 jqp_int_flavours_t flavour; 171 double value; 172 void *opaque; 173 } JQP_DOUBLE; 174 175 typedef struct JQP_OP { 176 jqp_unit_t type; 177 bool negate; 178 jqp_op_t value; 179 struct JQP_OP *next; 180 void *opaque; 181 } JQP_OP; 182 183 typedef struct JQP_JOIN { 184 jqp_unit_t type; 185 bool negate; 186 jqp_op_t value; 187 } JQP_JOIN; 188 189 typedef struct JQP_EXPR { 190 jqp_unit_t type; 191 struct JQP_JOIN *join; 192 struct JQP_OP *op; 193 JQPUNIT *left; 194 JQPUNIT *right; 195 struct JQP_EXPR *next; 196 bool prematched; 197 } JQP_EXPR; 198 199 typedef struct JQP_PROJECTION { 200 jqp_unit_t type; 201 struct JQP_STRING *value; 202 struct JQP_PROJECTION *next; 203 int16_t pos; // Current matching position, used in jql.c#_jql_project 204 int16_t cnt; // Number of projection sections, used in jql.c#_jql_project 205 206 #define JQP_PROJECTION_FLAG_EXCLUDE 0x01U 207 #define JQP_PROJECTION_FLAG_INCLUDE 0x02U 208 #define JQP_PROJECTION_FLAG_JOINS 0x04U 209 uint8_t flags; 210 } JQP_PROJECTION; 211 212 typedef struct JQP_QUERY { 213 jqp_unit_t type; 214 struct JQP_AUX *aux; 215 } JQP_QUERY; 216 217 //-- 218 219 union _JQP_UNIT { 220 jqp_unit_t type; 221 struct JQP_QUERY query; 222 struct JQP_EXPR_NODE exprnode; 223 struct JQP_EXPR_NODE_PK exprnode_pk; 224 struct JQP_FILTER filter; 225 struct JQP_NODE node; 226 struct JQP_EXPR expr; 227 struct JQP_JOIN join; 228 struct JQP_OP op; 229 struct JQP_STRING string; 230 struct JQP_INTEGER intval; 231 struct JQP_DOUBLE dblval; 232 struct JQP_JSON json; 233 struct JQP_PROJECTION projection; 234 }; 235 236 typedef enum { 237 STACK_UNIT = 1, 238 STACK_STRING, 239 STACK_INT, 240 STACK_FLOAT, 241 } jqp_stack_t; 242 243 typedef struct JQP_STACK { 244 jqp_stack_t type; 245 struct JQP_STACK *next; 246 struct JQP_STACK *prev; 247 union { 248 JQPUNIT *unit; 249 char *str; 250 int64_t i64; 251 double f64; 252 }; 253 } JQP_STACK; 254 255 #define JQP_AUX_STACKPOOL_NUM 128 256 257 typedef uint8_t jqp_query_mode_t; 258 259 #define JQP_QRY_COUNT ((jqp_query_mode_t) 0x01U) 260 #define JQP_QRY_NOIDX ((jqp_query_mode_t) 0x02U) 261 #define JQP_QRY_APPLY_DEL ((jqp_query_mode_t) 0x04U) 262 #define JQP_QRY_INVERSE ((jqp_query_mode_t) 0x08U) 263 #define JQP_QRY_APPLY_UPSERT ((jqp_query_mode_t) 0x10U) 264 265 #define JQP_QRY_AGGREGATE (JQP_QRY_COUNT) 266 267 typedef struct JQP_AUX { 268 int pos; 269 int stackn; 270 int num_placeholders; 271 int orderby_num; /**< Number of order-by blocks */ 272 iwrc rc; 273 jmp_buf fatal_jmp; 274 const char *buf; 275 IWXSTR *xerr; 276 IWPOOL *pool; 277 struct JQP_QUERY *query; 278 JQP_STACK *stack; 279 jql_create_mode_t mode; 280 // 281 struct JQP_EXPR_NODE *expr; 282 struct JQP_PROJECTION *projection; 283 JQP_STRING *start_placeholder; 284 JQP_STRING *end_placeholder; 285 JQP_STRING *orderby; 286 JBL_PTR *orderby_ptrs; /**< Order-by pointers, orderby_num - number of pointers allocated */ 287 JQP_OP *start_op; 288 JQP_OP *end_op; 289 JQPUNIT *skip; 290 JQPUNIT *limit; 291 JBL_NODE apply; 292 const char *apply_placeholder; 293 const char *first_anchor; 294 jqp_query_mode_t qmode; 295 bool negate; 296 bool has_keep_projections; 297 bool has_exclude_all_projection; 298 JQP_STACK stackpool[JQP_AUX_STACKPOOL_NUM]; 299 } JQP_AUX; 300 301 iwrc jqp_aux_create(JQP_AUX **auxp, const char *input); 302 303 void jqp_aux_destroy(JQP_AUX **auxp); 304 305 iwrc jqp_parse(JQP_AUX *aux); 306 307 iwrc jqp_print_query(const JQP_QUERY *q, jbl_json_printer pt, void *op); 308 309 iwrc jqp_alloc_orderby_pointers(const JQP_QUERY *q, JBL_PTR *optr, size_t *nptr); 310 311 iwrc jqp_print_filter_node_expr(const JQP_EXPR *e, jbl_json_printer pt, void *op); 312 313 #endif 314