Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024, 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #ifndef SQL_CATALOG_H
14 : #define SQL_CATALOG_H
15 :
16 : #include "sql_mem.h"
17 : #include "sql_list.h"
18 : #include "sql_hash.h"
19 : #include "mapi_querytype.h"
20 : #include "stream.h"
21 : #include "matomic.h"
22 :
23 : #define sql_shared_module_name "sql"
24 : #define sql_private_module_name "user"
25 :
26 : #define tr_none 1
27 : #define tr_readonly 2
28 : #define tr_writable 4
29 : #define tr_append 8
30 : #define tr_snapshot 16
31 : #define tr_serializable 32
32 :
33 : #define ACT_NO_ACTION 0
34 : #define ACT_CASCADE 1
35 : #define ACT_RESTRICT 2
36 : #define ACT_SET_NULL 3
37 : #define ACT_SET_DEFAULT 4
38 :
39 : #define DROP_RESTRICT 0
40 : #define DROP_CASCADE 1
41 : #define DROP_CASCADE_START 2
42 :
43 : #define PRIV_SELECT 1
44 : #define PRIV_UPDATE 2
45 : #define PRIV_INSERT 4
46 : #define PRIV_DELETE 8
47 : #define PRIV_EXECUTE 16
48 : #define PRIV_GRANT 32
49 : #define PRIV_TRUNCATE 64
50 : /* global privs */
51 : #define PRIV_COPYFROMFILE 1
52 : #define PRIV_COPYINTOFILE 2
53 :
54 : typedef enum sql_dependency {
55 : SCHEMA_DEPENDENCY = 1,
56 : TABLE_DEPENDENCY = 2,
57 : COLUMN_DEPENDENCY = 3,
58 : KEY_DEPENDENCY = 4,
59 : VIEW_DEPENDENCY = 5,
60 : USER_DEPENDENCY = 6,
61 : FUNC_DEPENDENCY = 7,
62 : TRIGGER_DEPENDENCY = 8,
63 : OWNER_DEPENDENCY = 9,
64 : INDEX_DEPENDENCY = 10,
65 : FKEY_DEPENDENCY = 11,
66 : SEQ_DEPENDENCY = 12,
67 : PROC_DEPENDENCY = 13,
68 : BEDROPPED_DEPENDENCY = 14, /*The object must be dropped when the dependent object is dropped independently of the DROP type.*/
69 : TYPE_DEPENDENCY = 15
70 : } sql_dependency;
71 :
72 : #define NO_DEPENDENCY 0
73 : #define HAS_DEPENDENCY 1
74 : #define CICLE_DEPENDENCY 2
75 : #define DEPENDENCY_CHECK_ERROR 3
76 : #define DEPENDENCY_CHECK_OK 0
77 :
78 : #define ROLE_PUBLIC 1
79 : #define ROLE_SYSADMIN 2
80 : #define USER_MONETDB 3
81 :
82 : #define SCALE_NONE 0
83 : #define SCALE_FIX 1 /* many numerical functions require equal
84 : scales/precision for all their inputs */
85 : #define MAX_BITS 2
86 : #define SCALE_MUL 3 /* multiplication gives the sum of scales */
87 : #define SCALE_DIV 4 /* div on the other hand reduces the scales */
88 : #define DIGITS_ADD 5 /* some types grow under functions (concat) */
89 : #define INOUT 6 /* output type equals input type (of first input) */
90 : #define SCALE_EQ 7 /* user defined functions need equal scales */
91 :
92 : #define RDONLY 0
93 : #define RD_INS 1
94 : #define RD_UPD_ID 2
95 : #define RD_UPD_VAL 3
96 : #define QUICK 4
97 : #define RD_EXT 5
98 :
99 : #define MS_VALUE 0
100 : #define MS_SETOF 1
101 : #define MS_ARRAY 2
102 : #define MS_VECTOR 3
103 :
104 : /* the following list of macros are used by rel_rankop function */
105 : #define UNBOUNDED_PRECEDING_BOUND 0
106 : #define UNBOUNDED_FOLLOWING_BOUND 1
107 : #define CURRENT_ROW_BOUND 2
108 :
109 : #define FRAME_ROWS 0 /* number of rows (preceding/following) */
110 : #define FRAME_RANGE 1 /* logical range (based on the ordering column).
111 : Example:
112 : RANGE BETWEEN INTERVAL '1' MONTH PRECEDING
113 : AND INTERVAL '1' MONTH FOLLOWING */
114 : #define FRAME_GROUPS 2
115 : #define FRAME_UNBOUNDED_TILL_CURRENT_ROW 3
116 : #define FRAME_CURRENT_ROW_TILL_UNBOUNDED 4
117 : #define FRAME_ALL 5
118 : #define FRAME_CURRENT_ROW 6
119 :
120 : /* the following list of macros are used by SQLwindow_bound function */
121 : #define BOUND_FIRST_HALF_PRECEDING 0
122 : #define BOUND_FIRST_HALF_FOLLOWING 1
123 : #define BOUND_SECOND_HALF_PRECEDING 2
124 : #define BOUND_SECOND_HALF_FOLLOWING 3
125 : #define CURRENT_ROW_PRECEDING 4
126 : #define CURRENT_ROW_FOLLOWING 5
127 :
128 : #define EXCLUDE_NONE 0 /* nothing excluded (also the default) */
129 : #define EXCLUDE_CURRENT_ROW 1 /* exclude the current row */
130 : #define EXCLUDE_GROUP 2 /* exclude group */
131 : #define EXCLUDE_TIES 3 /* exclude group but not the current row */
132 :
133 : /* The following macros are used in properties field of sql_table */
134 : #define PARTITION_RANGE 1
135 : #define PARTITION_LIST 2
136 : #define PARTITION_COLUMN 4
137 : #define PARTITION_EXPRESSION 8
138 :
139 : #define STORAGE_MAX_VALUE_LENGTH 2048
140 :
141 : #define cur_user 1
142 : #define cur_role 2
143 :
144 : #define sql_max(i1,i2) ((i1)<(i2))?(i2):(i1)
145 :
146 : #define dt_schema "%dt%"
147 : #define isDeclaredSchema(s) (strcmp(s->base.name, dt_schema) == 0)
148 :
149 : extern const char *TID;
150 :
151 : typedef enum temp_t {
152 : SQL_PERSIST = 0,
153 : SQL_LOCAL_TEMP = 1,
154 : SQL_GLOBAL_TEMP = 2,
155 : SQL_DECLARED_TABLE = 3, /* variable inside a stored procedure */
156 : SQL_MERGE_TABLE = 4,
157 : /* SQL_STREAM = 5, stream tables are not used anymore */
158 : SQL_REMOTE = 6,
159 : SQL_REPLICA_TABLE = 7,
160 : SQL_UNLOGGED_TABLE = 8
161 : } temp_t;
162 :
163 : typedef enum comp_type {
164 : cmp_gt = 0,
165 : cmp_gte = 1,
166 : cmp_lte = 2,
167 : cmp_lt = 3,
168 : cmp_equal = 4,
169 : cmp_notequal = 5,
170 :
171 : cmp_filter = 6,
172 : cmp_or = 7,
173 : cmp_in = 8, /* in value list */
174 : cmp_notin = 9, /* not in value list */
175 :
176 : /* The following cmp_* are only used within stmt (not sql_exp) */
177 : cmp_all = 12, /* special case for crossproducts */
178 : cmp_project = 13, /* special case for projection joins */
179 : cmp_joined = 14, /* special case already joined */
180 : cmp_left_project = 15 /* last step of outer join */
181 : } comp_type;
182 :
183 : #define is_theta_exp(e) ((e) == cmp_gt || (e) == cmp_gte || (e) == cmp_lte ||\
184 : (e) == cmp_lt || (e) == cmp_equal || (e) == cmp_notequal)
185 :
186 : #define is_complex_exp(et) ((et) == cmp_or || (et) == cmp_in || (et) == cmp_notin || (et) == cmp_filter)
187 :
188 : #define is_equality_or_inequality_exp(et) ((et) == cmp_equal || (et) == cmp_notequal || (et) == cmp_in || (et) == cmp_notin)
189 :
190 : typedef enum commit_action_t {
191 : CA_COMMIT, /* commit rows, only for persistent tables */
192 : CA_DELETE, /* delete rows */
193 : CA_PRESERVE, /* preserve rows */
194 : CA_DROP /* drop table */
195 : } ca_t;
196 :
197 : typedef int sqlid;
198 :
199 : typedef struct sql_ref {
200 : int refcnt;
201 : } sql_ref;
202 :
203 : extern sql_ref *sql_ref_init(sql_ref *r);
204 : extern int sql_ref_inc(sql_ref *r);
205 : extern int sql_ref_dec(sql_ref *r);
206 :
207 : typedef void *sql_store;
208 :
209 : typedef struct sql_base {
210 : unsigned int
211 : new:1,
212 : deleted:1;
213 : ATOMIC_TYPE refcnt;
214 : sqlid id;
215 : char *name;
216 : } sql_base;
217 :
218 : #define isNew(x) ((x)->base.new)
219 : #define isDeleted(x) ((x)->base.deleted)
220 :
221 : extern void base_init(allocator *sa, sql_base * b, sqlid id, bool isnew, const char *name);
222 :
223 : typedef struct changeset {
224 : allocator *sa;
225 : fdestroy destroy;
226 : fkeyvalue fkeyvalue;
227 : struct list *set;
228 : struct list *dset;
229 : node *nelm;
230 : } changeset;
231 :
232 : typedef struct objlist {
233 : list *l;
234 : sql_hash *h;
235 : sql_store store;
236 : } objlist;
237 :
238 : struct sql_trans;
239 : struct sql_change;
240 : struct objectset;
241 : struct versionhead;
242 : struct os_iter {
243 : struct objectset *os;
244 : struct sql_trans *tr;
245 : struct versionhead *n;
246 : struct sql_hash_e *e;
247 : const char *name;
248 : };
249 :
250 : /* transaction changes */
251 : typedef int (*tc_valid_fptr) (struct sql_trans *tr, struct sql_change *c/*, ulng commit_ts, ulng oldest*/);
252 : typedef int (*tc_log_fptr) (struct sql_trans *tr, struct sql_change *c); /* write changes to the log */
253 : typedef int (*tc_commit_fptr) (struct sql_trans *tr, struct sql_change *c, ulng commit_ts, ulng oldest);/* commit/rollback changes */
254 : typedef int (*tc_cleanup_fptr) (sql_store store, struct sql_change *c, ulng oldest); /* garbage collection, ie cleanup structures when possible */
255 : typedef void (*destroy_fptr)(sql_store store, sql_base *b);
256 : typedef int (*validate_fptr)(struct sql_trans *tr, sql_base *b, int delete);
257 :
258 : extern struct objectset *os_new(allocator *sa, destroy_fptr destroy, bool temporary, bool unique, bool concurrent, bool nested, sql_store store);
259 : extern struct objectset *os_dup(struct objectset *os);
260 : extern void os_destroy(struct objectset *os, sql_store store);
261 : extern int /*ok, error (name existed) and conflict (added before) */ os_add(struct objectset *os, struct sql_trans *tr, const char *name, sql_base *b);
262 : extern int os_del(struct objectset *os, struct sql_trans *tr, const char *name, sql_base *b);
263 : extern int os_size(struct objectset *os, struct sql_trans *tr);
264 : extern int os_empty(struct objectset *os, struct sql_trans *tr);
265 : extern int os_remove(struct objectset *os, struct sql_trans *tr, const char *name);
266 : extern sql_base *os_find_name(struct objectset *os, struct sql_trans *tr, const char *name);
267 : extern sql_base *os_find_id(struct objectset *os, struct sql_trans *tr, sqlid id);
268 : /* iterating (for example for location functions) */
269 : extern void os_iterator(struct os_iter *oi, struct objectset *os, struct sql_trans *tr, const char *name /*optional*/);
270 : extern sql_base *oi_next(struct os_iter *oi);
271 : extern bool os_obj_intransaction(struct objectset *os, struct sql_trans *tr, sql_base *b);
272 : extern bool os_has_changes(struct objectset *os, struct sql_trans *tr);
273 :
274 : extern objlist *ol_new(allocator *sa, destroy_fptr destroy, sql_store store);
275 : extern void ol_destroy(objlist *ol, sql_store store);
276 : extern int ol_add(objlist *ol, sql_base *data);
277 : extern void ol_del(objlist *ol, sql_store store, node *data);
278 : extern node *ol_find_name(objlist *ol, const char *name);
279 : extern node *ol_find_id(objlist *ol, sqlid id);
280 : extern node *ol_rehash(objlist *ol, const char *oldname, node *n);
281 : #define ol_length(ol) (list_length(ol->l))
282 : #define ol_first_node(ol) (ol->l->h)
283 : #define ol_last_node(ol) (ol->l->t)
284 : #define ol_fetch(ol,nr) (list_fetch(ol->l, nr))
285 :
286 : extern void cs_new(changeset * cs, allocator *sa, fdestroy destroy, fkeyvalue hfunc);
287 : extern void cs_destroy(changeset * cs, void *data);
288 : extern changeset *cs_add(changeset * cs, void *elm, bool isnew);
289 : extern changeset *cs_del(changeset * cs, void *gdata, node *n, bool force);
290 : extern int cs_size(changeset * cs);
291 : extern node *cs_find_id(changeset * cs, sqlid id);
292 :
293 : typedef void *backend_code;
294 : typedef size_t backend_stack;
295 :
296 : typedef struct sql_schema {
297 : sql_base base;
298 : sqlid auth_id;
299 : sqlid owner;
300 : bit system; /* system or user schema */
301 : // TODO? int type; /* persistent, session local, transaction local */
302 :
303 : struct objectset *tables;
304 : struct objectset *types;
305 : struct objectset *funcs;
306 : struct objectset *seqs;
307 : struct objectset *keys; /* Names for keys, idxs, and triggers and parts are */
308 : struct objectset *idxs; /* global, but these objects are only */
309 : struct objectset *triggers; /* useful within a table */
310 : struct objectset *parts;
311 :
312 : char *internal; /* optional internal module name */
313 : sql_store store;
314 : } sql_schema;
315 :
316 : typedef struct sql_catalog {
317 : ATOMIC_TYPE schema_version;
318 :
319 : struct objectset *schemas;
320 : struct objectset *objects;
321 : } sql_catalog;
322 :
323 : typedef struct sql_trans {
324 : char *name;
325 :
326 : ulng ts; /* transaction start timestamp */
327 : ulng tid; /* transaction id */
328 :
329 : sql_store store; /* keep link into the global store */
330 : MT_Lock lock; /* lock protecting concurrent writes to the changes list */
331 : list *changes; /* list of changes */
332 :
333 : list *dropped; /* protection against recursive cascade action*/
334 : list *predicates; /* list of read predicates logged during update transactions */
335 : list *dependencies; /* list of dependencies created (list of sqlids from the objects) */
336 : list *depchanges; /* list of dependencies changed (it would be tested for conflicts at the end of the transaction) */
337 :
338 : lng logchanges; /* count number of changes to be applied to the wal */
339 : int active; /* is active transaction */
340 : int status; /* status of the last query */
341 :
342 : sql_catalog *cat;
343 : sql_schema *tmp; /* each session has its own tmp schema */
344 : struct objectset* localtmps;
345 :
346 : struct sql_trans *parent; /* multilevel transaction support */
347 : } sql_trans;
348 :
349 : typedef enum sql_class {
350 : EC_ANY,
351 : EC_TABLE,
352 : EC_BIT,
353 : EC_CHAR,
354 : EC_STRING,
355 : EC_BLOB,
356 : EC_POS,
357 : EC_NUM,
358 : EC_MONTH,
359 : EC_SEC,
360 : EC_DEC,
361 : EC_FLT,
362 : EC_TIME,
363 : EC_TIME_TZ,
364 : EC_DATE,
365 : EC_TIMESTAMP,
366 : EC_TIMESTAMP_TZ,
367 : EC_GEOM,
368 : EC_EXTERNAL,
369 : EC_MAX /* evaluated to the max value, should be always kept at the bottom */
370 : } sql_class;
371 :
372 : #define has_tz(e) (EC_TEMP_TZ(e))
373 : #define type_has_tz(t) has_tz((t)->type->eclass)
374 : #define EC_VARCHAR(e) ((e)==EC_CHAR||(e)==EC_STRING)
375 : #define EC_INTERVAL(e) ((e)==EC_MONTH||(e)==EC_SEC)
376 : #define EC_NUMBER(e) ((e)==EC_POS||(e)==EC_NUM||EC_INTERVAL(e)||(e)==EC_DEC||(e)==EC_FLT)
377 : #define EC_EXACTNUM(e) ((e)==EC_NUM||(e)==EC_DEC)
378 : #define EC_APPNUM(e) ((e)==EC_FLT)
379 : #define EC_COMPUTE(e) ((e)==EC_NUM||(e)==EC_FLT)
380 : #define EC_TEMP_TZ(e) ((e)==EC_TIME_TZ||(e)==EC_TIMESTAMP_TZ)
381 : #define EC_TEMP(e) ((e)==EC_TIME||(e)==EC_DATE||(e)==EC_TIMESTAMP||EC_TEMP_TZ(e))
382 : #define EC_TEMP_FRAC(e) ((e)==EC_TIME||(e)==EC_TIMESTAMP||EC_TEMP_TZ(e))
383 : #define EC_TEMP_NOFRAC(e) ((e)==EC_TIME||(e)==EC_TIMESTAMP)
384 : #define EC_SCALE(e) ((e)==EC_DEC||EC_TEMP_FRAC(e)||(e)==EC_SEC)
385 :
386 : typedef struct sql_type {
387 : sql_base base;
388 :
389 : union {
390 : char *impl; /* backend correspondent type */
391 : struct list *fields; /* list of fields (args) */
392 : } d;
393 : unsigned int digits;
394 : unsigned int scale; /* indicates how scale is used in functions */
395 : char localtype; /* localtype, need for coersions */
396 : unsigned char
397 : radix:6,
398 : composite:1;
399 : sql_class eclass; /* types are grouped into equivalence classes */
400 : sql_schema *s;
401 : } sql_type;
402 :
403 : /*
404 : typedef struct sql_alias {
405 : char *name;
406 : char *alias;
407 : } sql_alias;
408 : */
409 :
410 : #define ARG_IN 1
411 : #define ARG_OUT 0
412 :
413 : typedef struct sql_subtype {
414 : sql_type *type;
415 : unsigned int digits;
416 : unsigned int scale;
417 : unsigned char multiset;
418 : } sql_subtype;
419 :
420 : /* sql_func need type transform rules types are equal if underlying
421 : * types are equal + scale is equal if types do not mach we try type
422 : * conversions which means for simple 1 arg functions
423 : */
424 :
425 : typedef struct sql_arg {
426 : char *name;
427 : bte inout;
428 : sql_subtype type;
429 : } sql_arg;
430 :
431 : typedef enum sql_ftype {
432 : F_FUNC = 1,
433 : F_PROC = 2,
434 : F_AGGR = 3,
435 : F_FILT = 4,
436 : F_UNION = 5,
437 : F_ANALYTIC = 6,
438 : F_LOADER = 7
439 : } sql_ftype;
440 :
441 : #define IS_FUNC(f) ((f)->type == F_FUNC)
442 : #define IS_PROC(f) ((f)->type == F_PROC)
443 : #define IS_AGGR(f) ((f)->type == F_AGGR)
444 : #define IS_FILT(f) ((f)->type == F_FILT)
445 : #define IS_UNION(f) ((f)->type == F_UNION)
446 : #define IS_ANALYTIC(f) ((f)->type == F_ANALYTIC)
447 : #define IS_LOADER(f) ((f)->type == F_LOADER)
448 :
449 : #define FUNC_TYPE_STR(type, F, fn) \
450 : switch (type) { \
451 : case F_FUNC: \
452 : F = "FUNCTION"; \
453 : fn = "function"; \
454 : break; \
455 : case F_PROC: \
456 : F = "PROCEDURE"; \
457 : fn = "procedure"; \
458 : break; \
459 : case F_AGGR: \
460 : F = "AGGREGATE"; \
461 : fn = "aggregate"; \
462 : break; \
463 : case F_FILT: \
464 : F = "FILTER FUNCTION"; \
465 : fn = "filter function"; \
466 : break; \
467 : case F_UNION: \
468 : F = "UNION FUNCTION"; \
469 : fn = "table returning function"; \
470 : break; \
471 : case F_ANALYTIC: \
472 : F = "WINDOW FUNCTION"; \
473 : fn = "window function"; \
474 : break; \
475 : case F_LOADER: \
476 : F = "LOADER FUNCTION"; \
477 : fn = "loader function"; \
478 : break; \
479 : default: \
480 : assert(0); \
481 : }
482 :
483 : typedef enum sql_flang {
484 : FUNC_LANG_INT = 0, /* internal */
485 : FUNC_LANG_MAL = 1, /* create sql external mod.func */
486 : FUNC_LANG_SQL = 2, /* create ... sql function/procedure */
487 : FUNC_LANG_R = 3, /* create .. language R */
488 : FUNC_LANG_C = 4, /* create .. language C */
489 : FUNC_LANG_J = 5, /* create .. language JAVASCRIPT (not implemented) */
490 : /* this should probably be done in a better way */
491 : FUNC_LANG_PY = 6, /* create .. language PYTHON */
492 : /* values 8 and 9 were for Python 2 */
493 : FUNC_LANG_PY3 = 10, /* create .. language PYTHON3 */
494 : /* values 7 and 11 where old map python code */
495 : FUNC_LANG_CPP = 12 /* create .. language CPP */
496 : } sql_flang;
497 :
498 : #define LANG_EXT(l) ((l)>FUNC_LANG_SQL)
499 : #define UDF_LANG(l) ((l)!=FUNC_LANG_INT)
500 :
501 : typedef struct sql_func {
502 : sql_base base;
503 :
504 : char *mod;
505 : char *imp;
506 : /*
507 : Backend implementation function after it gets instantiated.
508 : During instantiation 'imp' will be set, but look for the 'instantiated' value to check if it's done or not.
509 : Note that functions other than SQL and MAL, don't require instantiation and 'imp' is always set.
510 : */
511 : sql_ftype type;
512 : list *ops; /* param list */
513 : list *res; /* list of results */
514 : sql_flang lang;
515 : char *query; /* sql code */
516 : bool
517 : semantics:1, /* When set to true, function incorporates some kind of null semantics */
518 : side_effect:1, /* if the function has side-effects */
519 : varres:1, /* variable output result */
520 : vararg:1, /* variable input arguments */
521 : system:1, /* system function */
522 : instantiated:1, /* if the function is instantiated */
523 : private:1, /* certain functions cannot be bound from user queries */
524 : order_required:1, /* some aggregate functions require an order */
525 : opt_order:1; /* some aggregate functions could have the inputs sorted */
526 :
527 : short fix_scale;
528 : /*
529 : SCALE_NONE => nothing
530 : SCALE_FIX => input scale fixing,
531 : SCALE_ADD => leave inputs as is and do add scales
532 : example numerical multiplication
533 : SCALE_SUB => first input scale, fix with second scale
534 : result scale is equal to first input
535 : example numerical division
536 : DIGITS_ADD => result digits, sum of args
537 : example string concat
538 : */
539 : sql_schema *s;
540 : allocator *sa;
541 : } sql_func;
542 :
543 : typedef struct sql_subfunc {
544 : sql_func *func;
545 : list *res;
546 : list *coltypes; /* we need this for copy into from loader */
547 : list *colnames; /* we need this for copy into from loader */
548 : char *sname, *tname; /* we need this for create table from loader */
549 : } sql_subfunc;
550 :
551 : typedef enum key_type {
552 : pkey,
553 : ukey, /* default behavior is that NULLS are distinct, e.g. there can be multiple null values in a column with regular UNIQUE constraint */
554 : fkey,
555 : unndkey, /* NULLS are not distinct, i.e. NULLS act as regular values for uniqueness checks */
556 : ckey /* CHECK constraint behaves as a key type*/
557 : } key_type;
558 :
559 : typedef struct sql_kc {
560 : struct sql_column *c;
561 : int trunc; /* 0 not truncated, >0 column is truncated */
562 : } sql_kc;
563 :
564 : typedef enum idx_type {
565 : hash_idx,
566 : join_idx,
567 : oph_idx, /* order preserving hash */
568 : no_idx, /* no idx, ie no storage */
569 : imprints_idx,
570 : ordered_idx,
571 : new_idx_types
572 : } idx_type;
573 :
574 : #define hash_index(t) ((t) == hash_idx || (t) == oph_idx)
575 : #define idx_has_column(t) (hash_index(t) || (t) == join_idx)
576 : #define oid_index(t) ((t) == join_idx)
577 : #define non_updatable_index(t) ((t) == ordered_idx || (t) == no_idx || !idx_has_column(t))
578 :
579 : typedef struct sql_idx {
580 : sql_base base;
581 : idx_type type; /* unique */
582 : struct list *columns; /* list of sql_kc */
583 : struct sql_table *t;
584 : struct sql_key *key; /* key */
585 : ATOMIC_PTR_TYPE data;
586 : } sql_idx;
587 :
588 : /* fkey consists of two of these */
589 : typedef struct sql_key { /* pkey, ukey, fkey */
590 : sql_base base;
591 : key_type type; /* pkey, ukey, fkey */
592 : sql_idx *idx; /* idx to accelerate key check */
593 : char *check; /* check condition*/
594 :
595 : struct list *columns; /* list of sql_kc */
596 : struct sql_table *t;
597 : int drop_action; /* only needed for alter drop key */
598 : } sql_key;
599 :
600 : typedef struct sql_ukey { /* pkey, ukey */
601 : sql_key k;
602 : //list *keys;
603 : } sql_ukey;
604 :
605 : typedef struct sql_fkey { /* fkey */
606 : sql_key k;
607 : /* 0=no action, 1=cascade, 2=restrict (default setting), 3=set null, 4=set default */
608 : int on_delete;
609 : int on_update;
610 : sqlid rkey;
611 : } sql_fkey;
612 :
613 : typedef struct sql_trigger {
614 : sql_base base;
615 : sht time; /* before or after */
616 : sht orientation; /* row or statement */
617 : sht event; /* insert, delete, update, truncate */
618 : /* int action_order; TODO, order within the set of triggers */
619 : struct list *columns; /* update trigger on list of (sql_kc) columns */
620 :
621 : struct sql_table *t;
622 : char *old_name; /* name referencing the old values */
623 : char *new_name; /* name referencing the new values */
624 :
625 : char *condition; /* when search condition, ie query */
626 : char *statement; /* action, ie list of sql statements */
627 : } sql_trigger;
628 :
629 : typedef struct sql_sequence {
630 : sql_base base;
631 : lng start;
632 : lng minvalue;
633 : lng maxvalue;
634 : lng increment;
635 : lng cacheinc;
636 : bit cycle;
637 : bit bedropped; /*Drop the SEQUENCE if you are dropping the column, e.g., SERIAL COLUMN".*/
638 : sql_schema *s;
639 : } sql_sequence;
640 :
641 : #define column_intern 16
642 : #define column_plain 0
643 :
644 : typedef struct sql_column {
645 : sql_base base;
646 : char column_type; /* 0 base column, 16 internal */
647 : sql_subtype type;
648 : int colnr;
649 : bit null;
650 : char *def;
651 : char unique; /* 0 NOT UNIQUE, 1 SUB_UNIQUE, 2 UNIQUE */
652 : int drop_action; /* only used for alter statements */
653 : char *storage_type;
654 : size_t dcount;
655 : void *min;
656 : void *max;
657 :
658 : struct sql_table *t;
659 : ATOMIC_PTR_TYPE data;
660 : } sql_column;
661 :
662 : typedef enum table_types {
663 : tt_table = 0, /* table */
664 : tt_view = 1, /* view */
665 : tt_merge_table = 3, /* multiple tables form one table */
666 : /* tt_stream = 4, stream tables are not used anymore */
667 : tt_remote = 5, /* stored on a remote server */
668 : tt_replica_table = 6, /* multiple replica of the same table */
669 : tt_unlogged_table = 7
670 : } table_types;
671 :
672 : #define TABLE_TYPE_DESCRIPTION(tt, properties) \
673 : ((tt) == tt_table) ? "TABLE" : ((tt) == tt_view) ? "VIEW" \
674 : : ((tt) == tt_merge_table && !(properties)) ? "MERGE TABLE" \
675 : : ((tt) == tt_remote) ? "REMOTE TABLE" \
676 : : ((tt) == tt_merge_table && ((properties)&PARTITION_LIST) == PARTITION_LIST) ? "LIST PARTITION TABLE" \
677 : : ((tt) == tt_merge_table && ((properties)&PARTITION_RANGE) == PARTITION_RANGE) ? "RANGE PARTITION TABLE" \
678 : : ((tt) == tt_unlogged_table) ? "UNLOGGED TABLE" \
679 : : "REPLICA TABLE"
680 :
681 : #define isTable(x) ((x)->type==tt_table || (x)->type==tt_unlogged_table)
682 : #define isView(x) ((x)->type==tt_view)
683 : #define isNonPartitionedTable(x) ((x)->type==tt_merge_table && !(x)->properties)
684 : #define isRangePartitionTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_RANGE) == PARTITION_RANGE)
685 : #define isListPartitionTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_LIST) == PARTITION_LIST)
686 : #define isPartitionedByColumnTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_COLUMN) == PARTITION_COLUMN)
687 : #define isPartitionedByExpressionTable(x) ((x)->type==tt_merge_table && ((x)->properties & PARTITION_EXPRESSION) == PARTITION_EXPRESSION)
688 : #define isMergeTable(x) ((x)->type==tt_merge_table)
689 : #define isRemote(x) ((x)->type==tt_remote)
690 : #define isReplicaTable(x) ((x)->type==tt_replica_table)
691 : #define isUnloggedTable(x) ((x)->type==tt_unlogged_table)
692 : #define isKindOfTable(x) (isTable(x) || isMergeTable(x) || isRemote(x) || isReplicaTable(x) || isUnloggedTable(x))
693 :
694 : #define TABLE_WRITABLE 0
695 : #define TABLE_READONLY 1
696 : #define TABLE_APPENDONLY 2
697 :
698 : typedef struct sql_part_value {
699 : ptr value;
700 : size_t length;
701 : } sql_part_value;
702 :
703 : typedef struct sql_part {
704 : sql_base base;
705 : struct sql_table *t; /* the merge table */
706 : sqlid member; /* the member of the merge table */
707 : bit with_nills; /* 0 no nills, 1 holds nills, NULL holds all values -> range FROM MINVALUE TO MAXVALUE WITH NULL */
708 : union {
709 : list *values; /* partition by values/list */
710 : struct sql_range { /* partition by range */
711 : ptr minvalue;
712 : ptr maxvalue;
713 : size_t minlength;
714 : size_t maxlength;
715 : } range;
716 : } part;
717 : } sql_part;
718 :
719 : typedef struct sql_expression {
720 : sql_subtype type; /* the returning sql_subtype of the expression */
721 : char *exp; /* the expression itself */
722 : list *cols; /* list of colnr of the columns of the table used in the expression */
723 : } sql_expression;
724 :
725 : typedef struct sql_table {
726 : sql_base base;
727 : sht type; /* table, view, etc */
728 : sht access; /* writable, readonly, appendonly */
729 : bit system; /* system or user table */
730 : bit bootstrap; /* system table created during bootstrap */
731 : bte properties; /* used for merge_tables */
732 : unsigned char
733 : composite:1,
734 : multiset:1;
735 : temp_t persistence; /* persistent, global or local temporary */
736 : ca_t commit_action; /* on commit action */
737 : char *query; /* views may require some query */
738 : int sz;
739 :
740 : sql_ukey *pkey;
741 : objlist *columns;
742 : objlist *idxs;
743 : objlist *keys;
744 : objlist *triggers;
745 : list *members; /* member tables of merge/replica tables */
746 : int drop_action; /* only needed for alter drop table */
747 :
748 : ATOMIC_PTR_TYPE data;
749 : sql_schema *s;
750 :
751 : union {
752 : struct sql_column *pcol; /* If it is partitioned on a column */
753 : struct sql_expression *pexp; /* If it is partitioned by an expression */
754 : } part;
755 : } sql_table;
756 :
757 : typedef struct res_col {
758 : char *tn;
759 : char *name;
760 : sql_subtype type;
761 : bat b;
762 : char mtype;
763 : unsigned virt:1, /* just needed for headers not part of output */
764 : composite:1,
765 : multiset:2,
766 : cached:1;
767 : int nrfields;
768 : ptr *p;
769 : } res_col;
770 :
771 : typedef struct res_table {
772 : int id;
773 : oid query_id;
774 : mapi_query_t query_type;
775 : int nr_cols;
776 : int nr_output_cols;
777 : int complex_type;
778 : BUN nr_rows;
779 : int output_col; /* col to use for output count */
780 : BUN cur_row;
781 : int cur_col;
782 : const char *tsep;
783 : const char *rsep;
784 : const char *ssep;
785 : const char *ns;
786 : res_col *cols;
787 : struct res_table *next;
788 : } res_table;
789 :
790 : typedef struct sql_session {
791 : allocator *sa;
792 : sql_trans *tr; /* active transaction */
793 :
794 : char *def_schema_name; /* users default schema name */
795 : char *schema_name; /* transaction's schema name */
796 : sql_schema *schema;
797 : ATOMIC_TYPE schema_version;
798 :
799 : char ac_on_commit; /* if 1, auto_commit should be enabled on
800 : commit, rollback, etc. */
801 : char auto_commit;
802 : int level; /* TRANSACTION isolation level */
803 : int status; /* status, ok/error */
804 : backend_stack stk;
805 : } sql_session;
806 :
807 : #define sql_base_loop(l, n) for (n=l->h; n; n=n->next)
808 :
809 : extern int base_key(sql_base *b);
810 : extern node *list_find_name(list *l, const char *name);
811 : extern node *list_find_id(list *l, sqlid id);
812 : extern node *list_find_base_id(list *l, sqlid id);
813 :
814 : extern sql_key *find_sql_key(sql_table *t, const char *kname);
815 : extern sql_key *sql_trans_find_key(sql_trans *tr, sqlid id);
816 : extern sql_key *schema_find_key(sql_trans *tr, sql_schema *s, const char *name);
817 :
818 : extern sql_idx *find_sql_idx(sql_table *t, const char *kname);
819 : extern sql_idx *sql_trans_find_idx(sql_trans *tr, sqlid id);
820 : extern sql_idx *schema_find_idx(sql_trans *tr, sql_schema *s, const char *name);
821 : extern sql_idx *schema_find_idx_id(sql_trans *tr, sql_schema *s, sqlid id);
822 :
823 : extern sql_column *find_sql_column(sql_table *t, const char *cname);
824 : extern sql_column *find_sql_column_id(sql_table *t, sqlid col_id);
825 :
826 : extern sql_table *find_sys_table(sql_trans *tr, const char *tname);
827 : extern sql_table *find_sql_table(sql_trans *tr, sql_schema *s, const char *tname);
828 : extern sql_table *find_sql_table_id(sql_trans *tr, sql_schema *s, sqlid id);
829 : extern sql_table *sql_trans_find_table(sql_trans *tr, sqlid id);
830 :
831 : extern sql_sequence *find_sql_sequence(sql_trans *tr, sql_schema *s, const char *sname);
832 :
833 : extern sql_schema *find_sql_schema(sql_trans *t, const char *sname);
834 : extern sql_schema *find_sql_schema_id(sql_trans *t, sqlid id);
835 :
836 : extern sql_type *find_sql_type(sql_trans *tr, sql_schema * s, const char *tname);
837 : extern sql_type *sql_trans_bind_type(sql_trans *tr, sql_schema *s, const char *name);
838 : extern sql_type *sql_trans_find_type(sql_trans *tr, sql_schema *s /*optional */, sqlid id);
839 : extern sql_func *sql_trans_find_func(sql_trans *tr, sqlid id);
840 : extern sql_trigger *sql_trans_find_trigger(sql_trans *tr, sqlid id);
841 : extern sql_trigger *schema_find_trigger(sql_trans *tr, sql_schema *s, const char *name);
842 :
843 : extern void find_partition_type(sql_subtype *tpe, sql_table *mt);
844 : extern void *sql_values_list_element_validate_and_insert(void *v1, void *v2, void *tpe, int* res);
845 : extern void *sql_range_part_validate_and_insert(void *v1, void *v2, void *tpe);
846 : extern void *sql_values_part_validate_and_insert(void *v1, void *v2, void *tpe);
847 :
848 : typedef struct {
849 : BAT *b;
850 : char* name;
851 : void* def;
852 : } sql_emit_col;
853 :
854 : extern int nested_mergetable(sql_trans *tr, sql_table *t, const char *sname, const char *tname);
855 : extern bool is_column_unique(sql_column *c);
856 : sql_export sql_part *partition_find_part(sql_trans *tr, sql_table *pt, sql_part *pp);
857 : extern node *members_find_child_id(list *l, sqlid id);
858 :
859 : #define outside_str 1
860 : #define inside_str 2
861 :
862 : #define extracting_schema 1
863 : #define extracting_sequence 2
864 :
865 : static inline void
866 169 : extract_schema_and_sequence_name(allocator *sa, char *default_value, char **schema, char **sequence)
867 : {
868 169 : int status = outside_str, identifier = extracting_schema;
869 169 : char next_identifier[1024]; /* needs one extra character for null terminator */
870 169 : size_t bp = 0;
871 :
872 2678 : for (size_t i = 0; default_value[i]; i++) {
873 2678 : char next = default_value[i];
874 :
875 2678 : if (next == '"') {
876 507 : if (status == inside_str && default_value[i + 1] == '"') {
877 0 : next_identifier[bp++] = '"';
878 0 : i++; /* has to advance two positions */
879 338 : } else if (status == inside_str) {
880 338 : next_identifier[bp++] = '\0';
881 338 : if (identifier == extracting_schema) {
882 169 : *schema = SA_STRDUP(sa, next_identifier);
883 169 : identifier = extracting_sequence;
884 169 : } else if (identifier == extracting_sequence) {
885 169 : *sequence = SA_STRDUP(sa, next_identifier);
886 169 : break; /* done extracting */
887 : }
888 : bp = 0;
889 : status = outside_str;
890 : } else {
891 : assert(status == outside_str);
892 : status = inside_str;
893 : }
894 2171 : } else if (next == '.') {
895 169 : if (status == outside_str && default_value[i + 1] == '"') {
896 : status = inside_str;
897 : i++; /* has to advance two positions */
898 : } else {
899 0 : assert(status == inside_str);
900 0 : next_identifier[bp++] = '.'; /* used inside an identifier name */
901 : }
902 2002 : } else if (status == inside_str) {
903 2002 : next_identifier[bp++] = next;
904 : } else {
905 : assert(status == outside_str);
906 : }
907 : }
908 169 : }
909 :
910 : #define isTempTable(x) ((x)->persistence!=SQL_PERSIST)
911 : #define isGlobal(x) ((x)->persistence!=SQL_LOCAL_TEMP && (x)->persistence!=SQL_DECLARED_TABLE)
912 : #define isGlobalTemp(x) ((x)->persistence==SQL_GLOBAL_TEMP)
913 : #define isLocalTemp(x) ((x)->persistence==SQL_LOCAL_TEMP)
914 : #define isTempSchema(x) (strcmp((x)->base.name, "tmp") == 0)
915 : #define isDeclaredTable(x) ((x)->persistence==SQL_DECLARED_TABLE)
916 :
917 : typedef enum store_type {
918 : store_bat, /* delta bats, ie multi user read/write */
919 : store_tst,
920 : store_mem
921 : } store_type;
922 :
923 : extern void arg_destroy(sql_store store, sql_arg *a);
924 : extern void part_value_destroy(sql_store store, sql_part_value *pv);
925 :
926 : typedef struct atom {
927 : int isnull;
928 : sql_subtype tpe;
929 : ValRecord data;
930 : } atom;
931 :
932 : /* duplicate atom */
933 : extern ValPtr SA_VALcopy(allocator *sa, ValPtr d, const ValRecord *s);
934 : extern atom *atom_copy(allocator *sa, atom *a);
935 :
936 : typedef struct pl {
937 : sql_column *c;
938 : unsigned int cmp;
939 : atom *r; /* if r is NULL then a full match is required */
940 : atom *f; /* make it match range expressions */
941 : uint8_t
942 : anti:1,
943 : semantics:1;
944 : } pl;
945 :
946 : typedef int msid_t;
947 : typedef int msindex_t;
948 : #define MSEL_NAME "elements"
949 : #define MSID_NAME "ms_id"
950 : #define MSNR_NAME "ms_nr"
951 : #define MSID_TYPENAME "int"
952 : #define MSNR_TYPENAME "int"
953 :
954 : #endif /* SQL_CATALOG_H */
|