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 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /* multi version catalog */
14 :
15 : #include "monetdb_config.h"
16 : #include "gdk.h"
17 :
18 : #include "sql_mvc.h"
19 : #include "sql_qc.h"
20 : #include "sql_types.h"
21 : #include "sql_env.h"
22 : #include "sql_semantic.h"
23 : #include "sql_partition.h"
24 : #include "sql_privileges.h"
25 : #include "mapi_querytype.h"
26 : #include "rel_rel.h"
27 : #include "rel_exp.h"
28 : #include "rel_semantic.h"
29 : #include "rel_unnest.h"
30 : #include "rel_optimizer.h"
31 : #include "rel_statistics.h"
32 :
33 : #include "mal_authorize.h"
34 : #include "mal_profiler.h"
35 : #include "mal_exception.h"
36 : #include "mal_interpreter.h"
37 :
38 : static void
39 221 : sql_create_comments(mvc *m, sql_schema *s)
40 : {
41 221 : sql_table *t = NULL;
42 221 : sql_column *c = NULL;
43 221 : sql_key *k = NULL;
44 :
45 221 : mvc_create_table(&t, m, s, "comments", tt_table, 1, SQL_PERSIST, 0, -1, 0);
46 221 : mvc_create_column_(&c, m, t, "id", "int", 32);
47 221 : sql_trans_create_ukey(&k, m->session->tr, t, "comments_id_pkey", pkey);
48 221 : sql_trans_create_kc(m->session->tr, k, c);
49 221 : sql_trans_key_done(m->session->tr, k);
50 221 : sql_trans_create_dependency(m->session->tr, c->base.id, k->idx->base.id, INDEX_DEPENDENCY);
51 221 : mvc_create_column_(&c, m, t, "remark", "varchar", 65000);
52 221 : sql_trans_alter_null(m->session->tr, c, 0);
53 221 : }
54 :
55 : static sql_table *
56 474 : mvc_init_create_view(mvc *m, sql_schema *s, const char *name, const char *query)
57 : {
58 474 : sql_table *t = NULL;
59 :
60 474 : mvc_create_view(&t, m, s, name, SQL_PERSIST, query, 1);
61 474 : if (t) {
62 474 : char *buf;
63 474 : sql_rel *r = NULL;
64 :
65 474 : if (!(buf = sa_strdup(m->ta, t->query))) {
66 0 : (void) sql_error(m, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
67 0 : return NULL;
68 : }
69 :
70 474 : r = rel_parse(m, s, buf, m_deps);
71 474 : if (r)
72 474 : r = sql_processrelation(m, r, 0, 0, 0, 0);
73 474 : if (r) {
74 474 : list *blist = rel_dependencies(m, r);
75 474 : if (mvc_create_dependencies(m, blist, t->base.id, VIEW_DEPENDENCY)) {
76 0 : sa_reset(m->ta);
77 0 : (void) sql_error(m, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
78 0 : return NULL;
79 : }
80 : }
81 474 : sa_reset(m->ta);
82 474 : assert(r);
83 : }
84 474 : return t;
85 : }
86 :
87 : #define MVC_INIT_DROP_TABLE(SQLID, TNAME, VIEW, NCOL) \
88 : do { \
89 : str output; \
90 : t = mvc_bind_table(m, s, TNAME); \
91 : SQLID = t->base.id; \
92 : for (int i = 0; i < NCOL; i++) { \
93 : sql_column *col = mvc_bind_column(m, t, VIEW[i].name); \
94 : VIEW[i].oldid = col->base.id; \
95 : } \
96 : if ((output = mvc_drop_table(m, s, t, 0)) != MAL_SUCCEED) { \
97 : mvc_destroy(m); \
98 : mvc_exit(store); \
99 : TRC_CRITICAL(SQL_TRANS, \
100 : "Initialization error: %s\n", output); \
101 : freeException(output); \
102 : return NULL; \
103 : } \
104 : } while (0)
105 :
106 : struct view_t {
107 : const char *name;
108 : const char *type;
109 : unsigned int digits;
110 : sqlid oldid;
111 : sqlid newid;
112 : };
113 :
114 : static void
115 64 : mvc_fix_depend(mvc *m, sql_column *depids, struct view_t *v, int n)
116 : {
117 64 : sqlstore *store = m->store;
118 64 : oid rid;
119 64 : rids *rs;
120 :
121 736 : for (int i = 0; i < n; i++) {
122 1344 : rs = store->table_api.rids_select(m->session->tr, depids,
123 672 : &v[i].oldid, &v[i].oldid, NULL);
124 672 : if (rs) {
125 4056 : while ((rid = store->table_api.rids_next(rs)), !is_oid_nil(rid)) {
126 3384 : store->table_api.column_update_value(m->session->tr, depids, rid, &v[i].newid);
127 : }
128 672 : store->table_api.rids_destroy(rs);
129 : }
130 : }
131 64 : }
132 :
133 : sql_store
134 341 : mvc_init(int debug, store_type store_tpe, int ro, int su, const char *initpasswd)
135 : {
136 341 : sqlstore *store = NULL;
137 341 : sql_schema *s;
138 341 : sql_table *t;
139 341 : mvc *m;
140 341 : str msg;
141 :
142 341 : TRC_DEBUG(SQL_TRANS, "Initialization\n");
143 341 : keyword_init();
144 341 : if (scanner_init_keywords() != 0) {
145 0 : TRC_CRITICAL(SQL_TRANS, "Malloc failure\n");
146 0 : return NULL;
147 : }
148 :
149 341 : if ((store = store_init(debug, store_tpe, ro, su)) == NULL) {
150 1 : keyword_exit();
151 1 : TRC_CRITICAL(SQL_TRANS, "Unable to create system tables\n");
152 1 : return NULL;
153 : }
154 :
155 340 : initialize_sql_functions_lookup(store->sa);
156 :
157 340 : m = mvc_create((sql_store)store, store->sa, 0, 0, NULL, NULL);
158 340 : if (!m) {
159 0 : mvc_exit(store);
160 0 : TRC_CRITICAL(SQL_TRANS, "Malloc failure\n");
161 0 : return NULL;
162 : }
163 :
164 340 : assert(m->sa == NULL);
165 340 : m->sa = sa_create(m->pa);
166 340 : if (!m->sa) {
167 0 : mvc_destroy(m);
168 0 : mvc_exit(store);
169 0 : TRC_CRITICAL(SQL_TRANS, "Malloc failure\n");
170 0 : return NULL;
171 : }
172 :
173 340 : if (store->first || store->catalog_version) {
174 237 : sqlid tid = 0, cid = 0;
175 237 : struct view_t tview[10] = {
176 : {
177 : .name = "id",
178 : .type = "int",
179 : .digits = 32,
180 : },
181 : {
182 : .name = "name",
183 : .type = "varchar",
184 : .digits = 1024,
185 : },
186 : {
187 : .name = "schema_id",
188 : .type = "int",
189 : .digits = 32,
190 : },
191 : {
192 : .name = "query",
193 : .type = "varchar",
194 : .digits = 1 << 20,
195 : },
196 : {
197 : .name = "type",
198 : .type = "smallint",
199 : .digits = 16,
200 : },
201 : {
202 : .name = "system",
203 : .type = "boolean",
204 : .digits = 1,
205 : },
206 : {
207 : .name = "commit_action",
208 : .type = "smallint",
209 : .digits = 16,
210 : },
211 : {
212 : .name = "access",
213 : .type = "smallint",
214 : .digits = 16,
215 : },
216 : {
217 : .name = "temporary",
218 : .type = "smallint",
219 : .digits = 16,
220 : },
221 : {
222 : 0
223 : },
224 237 : }, cview[11] = {
225 : {
226 : .name = "id",
227 : .type = "int",
228 : .digits = 32,
229 : },
230 : {
231 : .name = "name",
232 : .type = "varchar",
233 : .digits = 1024,
234 : },
235 : {
236 : .name = "type",
237 : .type = "varchar",
238 : .digits = 1024,
239 : },
240 : {
241 : .name = "type_digits",
242 : .type = "int",
243 : .digits = 32,
244 : },
245 : {
246 : .name = "type_scale",
247 : .type = "int",
248 : .digits = 32,
249 : },
250 : {
251 : .name = "table_id",
252 : .type = "int",
253 : .digits = 32,
254 : },
255 : {
256 : .name = "default",
257 : .type = "varchar",
258 : .digits = STORAGE_MAX_VALUE_LENGTH,
259 : },
260 : {
261 : .name = "null",
262 : .type = "boolean",
263 : .digits = 1,
264 : },
265 : {
266 : .name = "number",
267 : .type = "int",
268 : .digits = 32,
269 : },
270 : {
271 : .name = "storage",
272 : .type = "varchar",
273 : .digits = 2048,
274 : },
275 : {
276 : 0
277 : },
278 : };
279 237 : if (mvc_trans(m) < 0) {
280 0 : mvc_destroy(m);
281 0 : mvc_exit(store);
282 0 : TRC_CRITICAL(SQL_TRANS, "Failed to start transaction\n");
283 0 : return NULL;
284 : }
285 237 : s = m->session->schema = mvc_bind_schema(m, "sys");
286 237 : assert(m->session->schema != NULL);
287 :
288 237 : if (!store->first) {
289 160 : MVC_INIT_DROP_TABLE(tid, "tables", tview, 9);
290 176 : MVC_INIT_DROP_TABLE(cid, "columns", cview, 10);
291 : }
292 :
293 237 : t = mvc_init_create_view(m, s, "tables", "SELECT \"id\", \"name\", \"schema_id\", \"query\", CAST(CASE WHEN \"system\" THEN \"type\" + 10 /* system table/view */ ELSE (CASE WHEN \"commit_action\" = 0 THEN \"type\" /* table/view */ ELSE \"type\" + 20 /* global temp table */ END) END AS SMALLINT) AS \"type\", \"system\", \"commit_action\", \"access\", CASE WHEN (NOT \"system\" AND \"commit_action\" > 0) THEN 1 ELSE 0 END AS \"temporary\" FROM \"sys\".\"_tables\" WHERE \"type\" <> 2 UNION ALL SELECT \"id\", \"name\", \"schema_id\", \"query\", CAST(\"type\" + 30 /* local temp table */ AS SMALLINT) AS \"type\", \"system\", \"commit_action\", \"access\", 1 AS \"temporary\" FROM \"tmp\".\"_tables\";");
294 237 : if (!t) {
295 0 : mvc_destroy(m);
296 0 : mvc_exit(store);
297 0 : TRC_CRITICAL(SQL_TRANS, "Failed to create 'tables' view\n");
298 0 : return NULL;
299 : }
300 :
301 2370 : for (int i = 0; i < 9; i++) {
302 2133 : sql_column *col = NULL;
303 :
304 2133 : mvc_create_column_(&col, m, t, tview[i].name, tview[i].type, tview[i].digits);
305 2133 : if (col == NULL) {
306 0 : mvc_destroy(m);
307 0 : mvc_exit(store);
308 0 : TRC_CRITICAL(SQL_TRANS,
309 : "Initialization: creation of sys.tables column %s failed\n", tview[i].name);
310 0 : return NULL;
311 : }
312 2133 : tview[i].newid = col->base.id;
313 : }
314 :
315 237 : if (!store->first) {
316 16 : int pub = ROLE_PUBLIC;
317 16 : int p = PRIV_SELECT;
318 16 : int zero = 0;
319 16 : sql_table *privs = find_sql_table(m->session->tr, s, "privileges");
320 16 : sql_table *deps = find_sql_table(m->session->tr, s, "dependencies");
321 16 : store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
322 16 : assert(tview[9].name == NULL);
323 16 : tview[9].oldid = tid;
324 16 : tview[9].newid = t->base.id;
325 16 : mvc_fix_depend(m, find_sql_column(deps, "id"), tview, 10);
326 16 : mvc_fix_depend(m, find_sql_column(deps, "depend_id"), tview, 10);
327 : }
328 :
329 237 : t = mvc_init_create_view(m, s, "columns", "SELECT * FROM (SELECT p.* FROM \"sys\".\"_columns\" AS p UNION ALL SELECT t.* FROM \"tmp\".\"_columns\" AS t) AS columns;");
330 237 : if (!t) {
331 0 : mvc_destroy(m);
332 0 : mvc_exit(store);
333 0 : TRC_CRITICAL(SQL_TRANS, "Failed to create 'columns' view\n");
334 0 : return NULL;
335 : }
336 2607 : for (int i = 0; i < 10; i++) {
337 2370 : sql_column *col = NULL;
338 :
339 2370 : mvc_create_column_(&col, m, t, cview[i].name, cview[i].type, cview[i].digits);
340 2370 : if (col == NULL) {
341 0 : mvc_destroy(m);
342 0 : mvc_exit(store);
343 0 : TRC_CRITICAL(SQL_TRANS,
344 : "Initialization: creation of sys.tables column %s failed\n", cview[i].name);
345 0 : return NULL;
346 : }
347 2370 : cview[i].newid = col->base.id;
348 : }
349 :
350 237 : if (!store->first) {
351 16 : int pub = ROLE_PUBLIC;
352 16 : int p = PRIV_SELECT;
353 16 : int zero = 0;
354 16 : sql_table *privs = find_sql_table(m->session->tr, s, "privileges");
355 16 : sql_table *deps = find_sql_table(m->session->tr, s, "dependencies");
356 16 : store->table_api.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
357 16 : assert(cview[10].name == NULL);
358 16 : cview[10].oldid = cid;
359 16 : cview[10].newid = t->base.id;
360 16 : mvc_fix_depend(m, find_sql_column(deps, "id"), cview, 11);
361 16 : mvc_fix_depend(m, find_sql_column(deps, "depend_id"), cview, 11);
362 : } else {
363 221 : sql_create_env(m, s);
364 221 : sql_create_comments(m, s);
365 221 : sql_create_privileges(m, s, initpasswd);
366 : }
367 :
368 237 : if ((msg = mvc_commit(m, 0, NULL, false)) != MAL_SUCCEED) {
369 0 : TRC_CRITICAL(SQL_TRANS, "Unable to commit system tables: %s\n", (msg + 6));
370 0 : freeException(msg);
371 0 : mvc_destroy(m);
372 0 : mvc_exit(store);
373 0 : return NULL;
374 : }
375 : }
376 :
377 340 : if (mvc_trans(m) < 0) {
378 0 : mvc_destroy(m);
379 0 : mvc_exit(store);
380 0 : TRC_CRITICAL(SQL_TRANS, "Failed to start transaction\n");
381 0 : return NULL;
382 : }
383 :
384 : //as the sql_parser is not yet initialized in the storage, we determine the sql type of the sql_parts here
385 :
386 340 : struct os_iter si;
387 340 : os_iterator(&si, m->session->tr->cat->schemas, m->session->tr, NULL);
388 1861 : for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
389 1521 : sql_schema *ss = (sql_schema*)b;
390 1521 : struct os_iter oi;
391 1521 : os_iterator(&oi, ss->tables, m->session->tr, NULL);
392 25147 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
393 23626 : sql_table *tt = (sql_table*)b;
394 23626 : if (isPartitionedByColumnTable(tt) || isPartitionedByExpressionTable(tt)) {
395 45 : char *err;
396 45 : if ((err = parse_sql_parts(m, tt)) != NULL) {
397 0 : TRC_CRITICAL(SQL_TRANS, "Unable to start partitioned table: %s.%s: %s\n", ss->base.name, tt->base.name, err);
398 0 : freeException(err);
399 0 : mvc_destroy(m);
400 0 : mvc_exit(store);
401 0 : return NULL;
402 : }
403 : }
404 : }
405 : }
406 340 : if (sql_trans_convert_partitions(m->session->tr) < 0) {
407 0 : TRC_CRITICAL(SQL_TRANS, "Unable to start partitioned tables\n");
408 0 : mvc_destroy(m);
409 0 : mvc_exit(store);
410 0 : return NULL;
411 : }
412 :
413 340 : if ((msg = mvc_commit(m, 0, NULL, false)) != MAL_SUCCEED) {
414 0 : TRC_CRITICAL(SQL_TRANS, "Unable to commit system tables: %s\n", (msg + 6));
415 0 : freeException(msg);
416 0 : mvc_destroy(m);
417 0 : mvc_exit(store);
418 0 : return NULL;
419 : }
420 340 : mvc_destroy(m);
421 340 : return store;
422 : }
423 :
424 : void
425 339 : mvc_exit(sql_store store)
426 : {
427 339 : TRC_DEBUG(SQL_TRANS, "MVC exit\n");
428 339 : store_exit(store);
429 339 : keyword_exit();
430 339 : }
431 :
432 : void
433 339 : mvc_logmanager(sql_store store)
434 : {
435 339 : store_manager(store);
436 338 : }
437 :
438 : int
439 1445564 : mvc_status(mvc *m)
440 : {
441 1445564 : int res = m->session->status;
442 :
443 1445564 : return res;
444 : }
445 :
446 : int
447 0 : mvc_error_retry(mvc *m)
448 : {
449 0 : int res = m->session->status;
450 :
451 0 : if (!res || res == -ERR_AMBIGUOUS || res == -ERR_GROUPBY)
452 0 : return 0;
453 : return res;
454 : }
455 :
456 : int
457 0 : mvc_type(mvc *m)
458 : {
459 0 : int res = m->type;
460 :
461 0 : m->type = Q_PARSE;
462 0 : return res;
463 : }
464 :
465 : int
466 652826 : mvc_debug_on(mvc *m, int flg)
467 : {
468 :
469 652826 : if (m->debug & flg)
470 31 : return 1;
471 :
472 : return 0;
473 : }
474 :
475 : void
476 0 : mvc_cancel_session(mvc *m)
477 : {
478 0 : (void)sql_trans_end(m->session, SQL_ERR);
479 0 : }
480 :
481 : int
482 213924 : mvc_trans(mvc *m)
483 : {
484 213924 : int res = 0, err = m->session->status;
485 213924 : assert(!m->session->tr->active); /* can only start a new transaction */
486 :
487 213924 : TRC_INFO(SQL_TRANS, "Starting transaction\n");
488 213924 : res = sql_trans_begin(m->session);
489 214000 : if (m->qc && (res || err))
490 20755 : qc_restart(m->qc);
491 214000 : return res;
492 : }
493 :
494 : str
495 151846 : mvc_commit(mvc *m, int chain, const char *name, bool enabling_auto_commit)
496 : {
497 151846 : sql_trans *tr = m->session->tr;
498 151846 : int ok = SQL_OK;
499 151846 : str msg = MAL_SUCCEED, other;
500 151846 : char operation[BUFSIZ];
501 :
502 151846 : assert(tr);
503 151846 : assert(m->session->tr->active); /* only commit an active transaction */
504 151846 : TRC_DEBUG(SQL_TRANS,"Commit: %s\n", (name) ? name : "");
505 151837 : if(enabling_auto_commit)
506 0 : snprintf(operation, BUFSIZ, "Commit failed while enabling auto_commit: ");
507 151837 : else if(name)
508 45 : snprintf(operation, BUFSIZ, "SAVEPOINT: (%s)", name);
509 : else
510 151792 : snprintf(operation, BUFSIZ, "COMMIT:");
511 :
512 151837 : if (m->session->status < 0) {
513 12 : msg = createException(SQL, "sql.commit", SQLSTATE(40000) "%s transaction is aborted, will ROLLBACK instead", operation);
514 12 : if ((other = mvc_rollback(m, chain, name, false)) != MAL_SUCCEED)
515 0 : freeException(other);
516 12 : return msg;
517 : }
518 :
519 : /* savepoint, simply make a new sub transaction */
520 151825 : if (name && name[0] != '\0') {
521 45 : sql_trans *tr = m->session->tr;
522 45 : TRC_DEBUG(SQL_TRANS, "Savepoint\n");
523 45 : if (!(m->session->tr = sql_trans_create(m->store, tr, name)))
524 0 : return createException(SQL, "sql.commit", SQLSTATE(HY013) "%s allocation failure while creating savepoint", operation);
525 :
526 45 : if (!(m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name))) {
527 0 : m->session->tr = sql_trans_destroy(m->session->tr);
528 0 : return createException(SQL, "sql.commit", SQLSTATE(40000) "%s finished successfully, but the session's schema could not be found on the current transaction", operation);
529 : }
530 45 : m->type = Q_TRANS;
531 45 : TRC_INFO(SQL_TRANS, "Savepoint commit '%s' done\n", name);
532 45 : return msg;
533 : }
534 :
535 151780 : if (!tr->parent && !name) {
536 151782 : lng Tbegin = 0;
537 151782 : ulng ts_start = 0;
538 151782 : bool log_usec = profilerMode == 0 || m->session->auto_commit;
539 151782 : if(profilerStatus > 0) {
540 0 : if (log_usec) Tbegin = GDKusec();
541 0 : ts_start = m->session->tr->ts;
542 : }
543 :
544 151782 : const int state = sql_trans_end(m->session, ok);
545 :
546 151801 : if(profilerStatus > 0) {
547 0 : lng Tend = GDKusec();
548 0 : Client c = mal_clients+m->clientid;
549 0 : profilerEvent(NULL,
550 : &(struct NonMalEvent)
551 0 : { state == SQL_CONFLICT ? CONFLICT : COMMIT , c, Tend, &ts_start, &m->session->tr->ts, state == SQL_ERR, log_usec?Tend-Tbegin:0});
552 : }
553 151801 : switch (state) {
554 0 : case SQL_ERR:
555 0 : GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
556 434 : break;
557 434 : case SQL_CONFLICT:
558 :
559 : /* transaction conflict */
560 434 : return createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
561 : default:
562 151367 : break;
563 : }
564 151367 : if (chain) {
565 2 : if (sql_trans_begin(m->session) < 0)
566 0 : return createException(SQL, "sql.commit", SQLSTATE(40000) "%s finished successfully, but the session's schema could not be found while starting the next transaction", operation);
567 2 : m->session->auto_commit = 0; /* disable auto-commit while chaining */
568 : }
569 151367 : m->type = Q_TRANS;
570 151367 : TRC_INFO(SQL_TRANS,
571 : "Commit done\n");
572 151367 : return msg;
573 : }
574 :
575 : /* save points only */
576 : assert(name || tr->parent);
577 :
578 : /* commit and cleanup nested transactions */
579 0 : if (tr->parent) {
580 5 : while (tr->parent != NULL && ok == SQL_OK) {
581 0 : if ((ok = sql_trans_commit(tr)) == SQL_ERR)
582 0 : GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
583 7 : m->session->tr = tr = sql_trans_destroy(tr);
584 : }
585 5 : while (tr->parent != NULL)
586 0 : m->session->tr = tr = sql_trans_destroy(tr);
587 5 : if (ok != SQL_OK)
588 0 : msg = createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
589 : }
590 :
591 : /* if there is nothing to commit reuse the current transaction */
592 5 : if (list_empty(tr->changes)) {
593 0 : if (!chain) {
594 0 : switch (sql_trans_end(m->session, ok)) {
595 0 : case SQL_ERR:
596 0 : GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
597 0 : break;
598 0 : case SQL_CONFLICT:
599 0 : if (!msg)
600 0 : msg = createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
601 : break;
602 : default:
603 : break;
604 : }
605 : }
606 0 : m->type = Q_TRANS;
607 0 : TRC_INFO(SQL_TRANS,
608 : "Commit done (no changes)\n");
609 0 : return msg;
610 : }
611 :
612 5 : switch (sql_trans_end(m->session, ok)) {
613 0 : case SQL_ERR:
614 0 : GDKfatal("%s transaction commit failed; exiting (kernel error: %s)", operation, GDKerrbuf);
615 0 : break;
616 0 : case SQL_CONFLICT:
617 0 : if (!msg)
618 0 : msg = createException(SQL, "sql.commit", SQLSTATE(40001) "%s transaction is aborted because of concurrency conflicts, will ROLLBACK instead", operation);
619 : return msg;
620 : default:
621 5 : break;
622 : }
623 5 : if (chain) {
624 0 : if (sql_trans_begin(m->session) < 0) {
625 0 : if (!msg)
626 0 : msg = createException(SQL, "sql.commit", SQLSTATE(40000) "%s finished successfully, but the session's schema could not be found while starting the next transaction", operation);
627 0 : return msg;
628 : }
629 0 : m->session->auto_commit = 0; /* disable auto-commit while chaining */
630 : }
631 5 : m->type = Q_TRANS;
632 5 : TRC_INFO(SQL_TRANS,
633 : "Commit done\n");
634 : return msg;
635 : }
636 :
637 : str
638 62058 : mvc_rollback(mvc *m, int chain, const char *name, bool disabling_auto_commit)
639 : {
640 62058 : str msg = MAL_SUCCEED;
641 :
642 62058 : TRC_DEBUG(SQL_TRANS, "Rollback: %s\n", (name) ? name : "");
643 62058 : (void) disabling_auto_commit;
644 :
645 62058 : sql_trans *tr = m->session->tr;
646 62058 : assert(m->session->tr && m->session->tr->active); /* only abort an active transaction */
647 62058 : if (name && name[0] != '\0') {
648 38 : while (tr && (!tr->name || strcmp(tr->name, name) != 0))
649 20 : tr = tr->parent;
650 18 : if (!tr || !tr->name || strcmp(tr->name, name) != 0) {
651 2 : msg = createException(SQL, "sql.rollback", SQLSTATE(42000) "ROLLBACK TO SAVEPOINT: no such savepoint: '%s'", name);
652 2 : m->session->status = -1;
653 2 : return msg;
654 : }
655 : tr = m->session->tr;
656 34 : while (!tr->name || strcmp(tr->name, name) != 0) {
657 : /* make sure we do not reuse changed data */
658 18 : if (!list_empty(tr->changes))
659 9 : tr->status = 1;
660 18 : m->session->tr = tr = sql_trans_destroy(tr);
661 : }
662 : /* start a new transaction after rolling back */
663 16 : if (!(m->session->tr = tr = sql_trans_create(m->store, tr, name))) {
664 0 : msg = createException(SQL, "sql.rollback", SQLSTATE(HY013) "ROLLBACK TO SAVEPOINT: allocation failure while restarting savepoint");
665 0 : m->session->status = -1;
666 0 : return msg;
667 : }
668 16 : m->session->status = tr->parent->status;
669 16 : if (!(m->session->schema = find_sql_schema(tr, m->session->schema_name))) {
670 1 : msg = createException(SQL, "sql.rollback", SQLSTATE(40000) "ROLLBACK TO SAVEPOINT: finished successfully, but the session's schema could not be found on the current transaction");
671 1 : m->session->status = -1;
672 1 : return msg;
673 : }
674 : } else {
675 : /* first release all intermediate savepoints */
676 62056 : while (tr->parent != NULL)
677 17 : m->session-> tr = tr = sql_trans_destroy(tr);
678 : /* make sure we do not reuse changed data */
679 62039 : if (!list_empty(tr->changes))
680 1062 : tr->status = 1;
681 :
682 :
683 62037 : lng Tbegin = 0;
684 62037 : ulng ts_start = 0;
685 62037 : bool log_usec = profilerMode == 0 || m->session->auto_commit;
686 62037 : if(profilerStatus > 0) {
687 0 : if (log_usec) Tbegin = GDKusec();
688 0 : ts_start = m->session->tr->ts;
689 : }
690 62037 : (void) sql_trans_end(m->session, SQL_ERR);
691 :
692 62040 : if(profilerStatus > 0) {
693 0 : lng Tend = GDKusec();
694 0 : Client c = mal_clients+m->clientid;
695 0 : profilerEvent(NULL,
696 : &(struct NonMalEvent)
697 0 : { ROLLBACK , c, Tend, &ts_start, &m->session->tr->ts, 0, log_usec?Tend-Tbegin:0});
698 : }
699 62040 : if (chain) {
700 2 : if (sql_trans_begin(m->session) < 0) {
701 1 : msg = createException(SQL, "sql.rollback", SQLSTATE(40000) "ROLLBACK: finished successfully, but the session's schema could not be found while starting the next transaction");
702 1 : m->session->status = -1;
703 1 : return msg;
704 : }
705 1 : m->session->auto_commit = 0; /* disable auto-commit while chaining */
706 : }
707 : }
708 62054 : if (msg != MAL_SUCCEED) {
709 : m->session->status = -1;
710 : return msg;
711 : }
712 62054 : m->type = Q_TRANS;
713 62054 : TRC_INFO(SQL_TRANS,
714 : "Commit%s%s rolled back%s\n",
715 : name ? " " : "", name ? name : "",
716 : list_empty(tr->changes) ? " (no changes)" : "");
717 : return msg;
718 : }
719 :
720 : /* release all savepoints up including the given named savepoint
721 : * but keep the current changes.
722 : * */
723 : str
724 11 : mvc_release(mvc *m, const char *name)
725 : {
726 11 : sql_trans *tr = m->session->tr;
727 11 : str msg = MAL_SUCCEED;
728 :
729 11 : assert(tr && tr->active); /* only release active transactions */
730 :
731 11 : TRC_DEBUG(SQL_TRANS, "Release: %s\n", (name) ? name : "");
732 :
733 11 : if (!name && (msg = mvc_rollback(m, 0, name, false)) != MAL_SUCCEED) {
734 0 : m->session->status = -1;
735 0 : return msg;
736 : }
737 :
738 31 : while (tr && (!tr->name || strcmp(tr->name, name) != 0))
739 20 : tr = tr->parent;
740 11 : if (!tr || !tr->name || strcmp(tr->name, name) != 0) {
741 0 : msg = createException(SQL, "sql.release", SQLSTATE(42000) "RELEASE: no such savepoint: '%s'", name);
742 0 : m->session->status = -1;
743 0 : return msg;
744 : }
745 11 : tr = m->session->tr;
746 31 : while (!tr->name || strcmp(tr->name, name) != 0) {
747 : /* commit all intermediate savepoints */
748 20 : if (sql_trans_commit(tr) != SQL_OK)
749 0 : GDKfatal("release savepoints should not fail");
750 20 : m->session->tr = tr = sql_trans_destroy(tr);
751 : }
752 11 : _DELETE(m->session->tr->name); /* name will no longer be used */
753 11 : m->session->status = tr->status;
754 11 : if (!(m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name))) {
755 0 : msg = createException(SQL, "sql.release", SQLSTATE(40000) "RELEASE: finished successfully, but the session's schema could not be found on the current transaction");
756 0 : m->session->status = -1;
757 0 : return msg;
758 : }
759 :
760 11 : m->type = Q_TRANS;
761 11 : return msg;
762 : }
763 :
764 : static void
765 76016 : _free(void *dummy, void *data)
766 : {
767 76016 : (void)dummy;
768 76016 : GDKfree(data);
769 76027 : }
770 :
771 : mvc *
772 38370 : mvc_create(sql_store *store, allocator *pa, int clientid, int debug, bstream *rs, stream *ws)
773 : {
774 38370 : mvc *m;
775 38370 : str sys_str = NULL;
776 :
777 38370 : assert(pa);
778 38370 : m = SA_ZNEW(pa, mvc);
779 38370 : if (!m)
780 : return NULL;
781 :
782 38370 : TRC_DEBUG(SQL_TRANS, "MVC create\n");
783 :
784 38370 : m->errstr[0] = '\0';
785 : /* if an error exceeds the buffer we don't want garbage at the end */
786 38370 : m->errstr[ERRSIZE-1] = '\0';
787 :
788 38370 : m->qc = qc_create(pa, clientid, 0);
789 38370 : if (!m->qc) {
790 : return NULL;
791 : }
792 38370 : m->pa = pa;
793 38370 : m->sa = NULL;
794 38370 : m->ta = sa_create(m->pa);
795 : #if defined(__GNUC__) || defined(__clang__)
796 38370 : m->sp = (uintptr_t) __builtin_frame_address(0);
797 : #else
798 : m->sp = (uintptr_t)(&m);
799 : #endif
800 :
801 38370 : m->params = NULL;
802 38370 : m->sizeframes = MAXPARAMS;
803 38370 : m->frames = SA_NEW_ARRAY(pa, sql_frame*, m->sizeframes);
804 38370 : m->topframes = 0;
805 38370 : m->frame = 0;
806 :
807 38370 : m->use_views = false;
808 38370 : if (!m->frames) {
809 0 : qc_destroy(m->qc);
810 0 : return NULL;
811 : }
812 38370 : if (init_global_variables(m) < 0) {
813 0 : qc_destroy(m->qc);
814 0 : list_destroy(m->global_vars);
815 0 : return NULL;
816 : }
817 38370 : m->sym = NULL;
818 :
819 38370 : m->role_id = m->user_id = -1;
820 38370 : m->timezone = 0;
821 38370 : m->sql_optimizer = INT_MAX;
822 38370 : m->clientid = clientid;
823 :
824 38370 : m->emode = m_normal;
825 38370 : m->emod = mod_none;
826 38370 : m->reply_size = 100;
827 38370 : m->debug = debug;
828 :
829 38370 : m->label = 0;
830 38370 : m->cascade_action = NULL;
831 38370 : m->runs = NULL;
832 :
833 38370 : if (!(m->schema_path = list_create((fdestroy)_free))) {
834 0 : qc_destroy(m->qc);
835 0 : list_destroy(m->global_vars);
836 0 : return NULL;
837 : }
838 38370 : if (!(sys_str = _STRDUP("sys")) || !list_append(m->schema_path, sys_str)) {
839 0 : _DELETE(sys_str);
840 0 : qc_destroy(m->qc);
841 0 : list_destroy(m->global_vars);
842 0 : list_destroy(m->schema_path);
843 0 : return NULL;
844 : }
845 38370 : m->schema_path_has_sys = true;
846 38370 : m->schema_path_has_tmp = false;
847 38370 : m->no_int128 = false;
848 38370 : m->store = store;
849 :
850 38370 : m->session = sql_session_create(m->store, m->pa, 1 /*autocommit on*/);
851 38370 : if (!m->session) {
852 0 : qc_destroy(m->qc);
853 0 : list_destroy(m->global_vars);
854 0 : list_destroy(m->schema_path);
855 0 : return NULL;
856 : }
857 :
858 38370 : m->type = Q_PARSE;
859 :
860 38370 : scanner_init(&m->scanner, rs, ws);
861 38370 : return m;
862 : }
863 :
864 : void
865 38370 : mvc_destroy(mvc *m)
866 : {
867 38370 : sql_trans *tr;
868 :
869 38370 : TRC_DEBUG(SQL_TRANS, "MVC destroy\n");
870 38370 : tr = m->session->tr;
871 38370 : if (tr) {
872 38370 : if (m->session->tr->active)
873 0 : (void)sql_trans_end(m->session, SQL_ERR);
874 38370 : while (tr->parent)
875 0 : m->session->tr = tr = sql_trans_destroy(tr);
876 : }
877 38370 : sql_session_destroy(m->session);
878 :
879 38370 : list_destroy(m->global_vars);
880 38370 : list_destroy(m->schema_path);
881 38370 : stack_pop_until(m, 0);
882 :
883 38370 : if (m->scanner.log) /* close and destroy stream */
884 0 : close_stream(m->scanner.log);
885 :
886 38370 : m->sa = NULL;
887 38370 : m->ta = NULL;
888 38370 : if (m->qc)
889 38370 : qc_destroy(m->qc);
890 38370 : m->qc = NULL;
891 38370 : }
892 :
893 : sql_type *
894 37027 : mvc_bind_type(mvc *sql, const char *name)
895 : {
896 37027 : sql_type *t = sql_trans_bind_type(sql->session->tr, NULL, name);
897 37027 : TRC_DEBUG(SQL_TRANS, "Bind type: %s\n", name);
898 37027 : return t;
899 : }
900 :
901 : sql_type *
902 1794 : schema_bind_type(mvc *sql, sql_schema *s, const char *name)
903 : {
904 1794 : sql_type *t = find_sql_type(sql->session->tr, s, name);
905 :
906 1794 : (void) sql;
907 1794 : if (!t)
908 : return NULL;
909 8 : TRC_DEBUG(SQL_TRANS, "Schema bind type: %s\n", name);
910 : return t;
911 : }
912 :
913 : sql_schema *
914 8400076 : mvc_bind_schema(mvc *m, const char *sname)
915 : {
916 8400076 : sql_trans *tr = m->session->tr;
917 8400076 : sql_schema *s;
918 :
919 8400076 : if (!tr)
920 : return NULL;
921 :
922 8400076 : s = find_sql_schema(tr, sname);
923 8415053 : if (!s)
924 : return NULL;
925 8348261 : TRC_DEBUG(SQL_TRANS, "Bind schema: %s\n", sname);
926 : return s;
927 : }
928 :
929 : sql_table *
930 5100822 : mvc_bind_table(mvc *m, sql_schema *s, const char *tname)
931 : {
932 5100822 : sql_table *t = find_sql_table(m->session->tr, s, tname);
933 :
934 5148988 : (void) m;
935 5148988 : if (!t)
936 : return NULL;
937 :
938 4879084 : TRC_DEBUG(SQL_TRANS, "Bind table: %s.%s\n", s->base.name, tname);
939 : return t;
940 : }
941 :
942 : sql_column *
943 3832768 : mvc_bind_column(mvc *m, sql_table *t, const char *cname)
944 : {
945 3832768 : sql_column *c;
946 :
947 3832768 : (void)m;
948 3832768 : c = find_sql_column(t, cname);
949 3875036 : if (!c)
950 : return NULL;
951 3675201 : TRC_DEBUG(SQL_TRANS, "Bind column: %s.%s\n", t->base.name, cname);
952 : return c;
953 : }
954 :
955 : static sql_column *
956 0 : first_column(sql_table *t)
957 : {
958 0 : node *n = ol_first_node(t->columns);
959 :
960 0 : if (n)
961 0 : return n->data;
962 : return NULL;
963 : }
964 :
965 : sql_column *
966 0 : mvc_first_column(mvc *m, sql_table *t)
967 : {
968 0 : sql_column *c = first_column(t);
969 :
970 0 : (void) m;
971 0 : if (!c)
972 : return NULL;
973 0 : TRC_DEBUG(SQL_TRANS, "First column: %s.%s\n", t->base.name, c->base.name);
974 : return c;
975 : }
976 :
977 : sql_key *
978 6953 : mvc_bind_key(mvc *m, sql_schema *s, const char *kname)
979 : {
980 6953 : sql_key *k = schema_find_key(m->session->tr, s, kname);
981 :
982 6953 : if (!k)
983 : return NULL;
984 3 : TRC_DEBUG(SQL_TRANS, "Bind key: %s.%s\n", s->base.name, kname);
985 : return k;
986 : }
987 :
988 : sql_idx *
989 20713 : mvc_bind_idx(mvc *m, sql_schema *s, const char *iname)
990 : {
991 20713 : sql_idx *i = schema_find_idx(m->session->tr, s, iname);
992 :
993 20802 : if (!i)
994 : return NULL;
995 13640 : TRC_DEBUG(SQL_TRANS, "Bind index: %s.%s\n", s->base.name, iname);
996 : return i;
997 : }
998 :
999 : static int
1000 895 : uniqueKey(sql_key *k)
1001 : {
1002 895 : return (k->type == pkey || k->type == ukey);
1003 : }
1004 :
1005 : sql_key *
1006 885 : mvc_bind_ukey(sql_table *t, list *colnames)
1007 : {
1008 885 : node *cn;
1009 885 : node *cur;
1010 885 : sql_key *res = NULL;
1011 885 : int len = list_length(colnames);
1012 :
1013 885 : if (ol_length(t->keys))
1014 897 : for (cur = ol_first_node(t->keys); cur; cur = cur->next) {
1015 895 : node *cc;
1016 895 : sql_key *k = cur->data;
1017 :
1018 895 : if (uniqueKey(k) && list_length(k->columns) == len) {
1019 885 : res = k;
1020 1795 : for (cc = k->columns->h, cn = colnames->h; cc && cn; cc = cc->next, cn = cn->next) {
1021 915 : sql_kc *c = cc->data;
1022 915 : char *n = cn->data;
1023 :
1024 915 : if (strcmp(c->c->base.name, n) != 0) {
1025 : res = NULL;
1026 : break;
1027 : }
1028 : }
1029 885 : if (res)
1030 : break;
1031 : }
1032 : }
1033 885 : return res;
1034 : }
1035 :
1036 : sql_trigger *
1037 918 : mvc_bind_trigger(mvc *m, sql_schema *s, const char *tname)
1038 : {
1039 918 : sql_trigger *t = schema_find_trigger(m->session->tr, s, tname);
1040 :
1041 918 : if (!t)
1042 : return NULL;
1043 165 : TRC_DEBUG(SQL_TRANS, "Bind trigger: %s.%s\n", s->base.name, tname);
1044 : return t;
1045 : }
1046 :
1047 : int
1048 890 : mvc_create_type(mvc *sql, sql_schema *s, const char *name, unsigned int digits, unsigned int scale, int radix, const char *impl)
1049 : {
1050 890 : TRC_DEBUG(SQL_TRANS, "Create type: %s\n", name);
1051 890 : return sql_trans_create_type(sql->session->tr, s, name, digits, scale, radix, impl);
1052 : }
1053 :
1054 : int
1055 3 : mvc_drop_type(mvc *m, sql_schema *s, sql_type *t, int drop_action)
1056 : {
1057 3 : TRC_DEBUG(SQL_TRANS, "Drop type: %s %s\n", s->base.name, t->base.name);
1058 3 : if (t)
1059 5 : return sql_trans_drop_type(m->session->tr, s, t->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
1060 : return 0;
1061 : }
1062 :
1063 : int
1064 235592 : mvc_create_func(sql_func **f, mvc *m, allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang,
1065 : const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect)
1066 : {
1067 235592 : int lres = LOG_OK;
1068 :
1069 235592 : TRC_DEBUG(SQL_TRANS, "Create function: %s\n", name);
1070 235592 : if (sa) {
1071 117599 : *f = create_sql_func(m->store, sa, name, args, res, type, lang, mod, impl, query, varres, vararg, system, side_effect);
1072 117599 : (*f)->s = s;
1073 : } else
1074 117993 : lres = sql_trans_create_func(f, m->session->tr, s, name, args, res, type, lang, mod, impl, query, varres, vararg, system, side_effect);
1075 235592 : return lres;
1076 : }
1077 :
1078 : int
1079 774 : mvc_drop_func(mvc *m, sql_schema *s, sql_func *f, int drop_action)
1080 : {
1081 774 : TRC_DEBUG(SQL_TRANS, "Drop function: %s %s\n", s->base.name, f->base.name);
1082 1386 : return sql_trans_drop_func(m->session->tr, s, f->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
1083 : }
1084 :
1085 : int
1086 28 : mvc_drop_all_func(mvc *m, sql_schema *s, list *list_func, int drop_action)
1087 : {
1088 28 : TRC_DEBUG(SQL_TRANS, "Drop all functions: %s %s\n", s->base.name, ((sql_func *) list_func->h->data)->base.name);
1089 56 : return sql_trans_drop_all_func(m->session->tr, s, list_func, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
1090 : }
1091 :
1092 : int
1093 1055 : mvc_create_schema(mvc *m, const char *name, sqlid auth_id, sqlid owner)
1094 : {
1095 1055 : TRC_DEBUG(SQL_TRANS, "Create schema: %s %d %d\n", name, auth_id, owner);
1096 1055 : return sql_trans_create_schema(m->session->tr, name, auth_id, owner, NULL);
1097 : }
1098 :
1099 : int
1100 141 : mvc_drop_schema(mvc *m, sql_schema * s, int drop_action)
1101 : {
1102 141 : TRC_DEBUG(SQL_TRANS, "Drop schema: %s\n", s->base.name);
1103 213 : return sql_trans_drop_schema(m->session->tr, s->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
1104 : }
1105 :
1106 : int
1107 5691 : mvc_create_ukey(sql_key **kres, mvc *m, sql_table *t, const char *name, key_type kt)
1108 : {
1109 5691 : int res = LOG_OK;
1110 :
1111 5691 : TRC_DEBUG(SQL_TRANS, "Create ukey: %s %u\n", t->base.name, (unsigned) kt);
1112 5691 : if (t->persistence == SQL_DECLARED_TABLE)
1113 5691 : *kres = create_sql_ukey(m->store, m->sa, t, name, kt);
1114 : else
1115 0 : res = sql_trans_create_ukey(kres, m->session->tr, t, name, kt);
1116 5691 : return res;
1117 : }
1118 :
1119 : int
1120 6593 : mvc_create_key_done(mvc *m, sql_key *k)
1121 : {
1122 6593 : int res = LOG_OK;
1123 :
1124 6593 : if (k->t->persistence == SQL_DECLARED_TABLE)
1125 6593 : key_create_done(m->session->tr, m->sa, k);
1126 : else
1127 0 : res = sql_trans_key_done(m->session->tr, k);
1128 6593 : return res;
1129 : }
1130 :
1131 : int
1132 921 : mvc_create_fkey(sql_fkey **kres, mvc *m, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update)
1133 : {
1134 921 : int res = LOG_OK;
1135 :
1136 921 : TRC_DEBUG(SQL_TRANS, "Create fkey: %s %u %p\n", t->base.name, (unsigned) kt, rkey);
1137 921 : if (t->persistence == SQL_DECLARED_TABLE)
1138 921 : *kres = create_sql_fkey(m->store, m->sa, t, name, kt, rkey, on_delete, on_update);
1139 : else
1140 0 : res = sql_trans_create_fkey(kres, m->session->tr, t, name, kt, rkey, on_delete, on_update);
1141 921 : return res;
1142 : }
1143 :
1144 : int
1145 6266 : mvc_create_kc(mvc *m, sql_key *k, sql_column *c)
1146 : {
1147 6266 : int res = LOG_OK;
1148 :
1149 6266 : if (k->t->persistence == SQL_DECLARED_TABLE)
1150 6266 : create_sql_kc(m->store, m->sa, k, c);
1151 : else
1152 0 : res = sql_trans_create_kc(m->session->tr, k, c);
1153 6266 : return res;
1154 : }
1155 :
1156 : int
1157 942 : mvc_create_fkc(mvc *m, sql_fkey *fk, sql_column *c)
1158 : {
1159 942 : int res = LOG_OK;
1160 942 : sql_key *k = (sql_key*)fk;
1161 :
1162 942 : if (k->t->persistence == SQL_DECLARED_TABLE)
1163 942 : create_sql_kc(m->store, m->sa, k, c);
1164 : else
1165 0 : res = sql_trans_create_fkc(m->session->tr, fk, c);
1166 942 : return res;
1167 : }
1168 :
1169 : int
1170 142 : mvc_drop_key(mvc *m, sql_schema *s, sql_key *k, int drop_action)
1171 : {
1172 142 : TRC_DEBUG(SQL_TRANS, "Drop key: %s %s\n", s->base.name, k->base.name);
1173 142 : if (k->t->persistence == SQL_DECLARED_TABLE) {
1174 0 : drop_sql_key(k->t, k->base.id, drop_action);
1175 0 : return 0;
1176 : } else
1177 283 : return sql_trans_drop_key(m->session->tr, s, k->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
1178 : }
1179 :
1180 : int
1181 329 : mvc_create_idx(sql_idx **i, mvc *m, sql_table *t, const char *name, idx_type it)
1182 : {
1183 329 : int res = LOG_OK;
1184 :
1185 329 : TRC_DEBUG(SQL_TRANS, "Create index: %s %u\n", t->base.name, (unsigned) it);
1186 329 : if (t->persistence == SQL_DECLARED_TABLE)
1187 : /* declared tables should not end up in the catalog */
1188 329 : *i = create_sql_idx(m->store, m->sa, t, name, it);
1189 : else
1190 0 : res = sql_trans_create_idx(i, m->session->tr, t, name, it);
1191 329 : return res;
1192 : }
1193 :
1194 : int
1195 419 : mvc_create_ic(mvc *m, sql_idx *i, sql_column *c)
1196 : {
1197 419 : int res = LOG_OK;
1198 :
1199 419 : if (i->t->persistence == SQL_DECLARED_TABLE)
1200 : /* declared tables should not end up in the catalog */
1201 419 : create_sql_ic(m->store, m->sa, i, c);
1202 : else
1203 0 : res = sql_trans_create_ic(m->session->tr, i, c);
1204 419 : return res;
1205 : }
1206 :
1207 : int
1208 327 : mvc_create_idx_done(mvc *m, sql_idx *i)
1209 : {
1210 327 : int res = LOG_OK;
1211 :
1212 327 : (void) m;
1213 327 : (void) create_sql_idx_done(m->session->tr, i);
1214 327 : return res;
1215 : }
1216 :
1217 : int
1218 156 : mvc_drop_idx(mvc *m, sql_schema *s, sql_idx *i)
1219 : {
1220 156 : TRC_DEBUG(SQL_TRANS, "Drop index: %s %s\n", s->base.name, i->base.name);
1221 156 : if (i->t->persistence == SQL_DECLARED_TABLE) {
1222 : /* declared tables should not end up in the catalog */
1223 0 : drop_sql_idx(i->t, i->base.id);
1224 0 : return 0;
1225 : } else
1226 156 : return sql_trans_drop_idx(m->session->tr, s, i->base.id, DROP_RESTRICT);
1227 : }
1228 :
1229 : int
1230 332 : mvc_create_trigger(sql_trigger **tri, mvc *m, sql_table *t, const char *name, sht time, sht orientation, sht event, const char *old_name,
1231 : const char *new_name, const char *condition, const char *statement)
1232 : {
1233 332 : TRC_DEBUG(SQL_TRANS, "Create trigger: %s %d %d %d\n", t->base.name, time, orientation, event);
1234 332 : return sql_trans_create_trigger(tri, m->session->tr, t, name, time, orientation, event, old_name, new_name, condition, statement);
1235 : }
1236 :
1237 : int
1238 85 : mvc_drop_trigger(mvc *m, sql_schema *s, sql_trigger *tri)
1239 : {
1240 85 : TRC_DEBUG(SQL_TRANS, "Drop trigger: %s %s\n", s->base.name, tri->base.name);
1241 85 : return sql_trans_drop_trigger(m->session->tr, s, tri->base.id, DROP_RESTRICT);
1242 : }
1243 :
1244 : int
1245 10757 : mvc_create_table(sql_table **t, mvc *m, sql_schema *s, const char *name, int tt, bit system, int persistence, int commit_action, int sz, bit properties)
1246 : {
1247 10757 : char *err = NULL;
1248 10757 : int res = LOG_OK;
1249 :
1250 10757 : assert(s);
1251 10757 : TRC_DEBUG(SQL_TRANS, "Create table: %s %s %d %d %d %d %d\n", s->base.name, name, tt, system, persistence, commit_action, (int)properties);
1252 10757 : if (persistence == SQL_DECLARED_TABLE) {
1253 9431 : *t = create_sql_table(m->store, m->sa, name, tt, system, persistence, commit_action, properties);
1254 9431 : (*t)->s = s;
1255 : } else {
1256 1326 : res = sql_trans_create_table(t, m->session->tr, s, name, NULL, tt, system, persistence, commit_action, sz, properties);
1257 1326 : if (res == LOG_OK && isPartitionedByExpressionTable(*t) && (err = bootstrap_partition_expression(m, *t, 1))) {
1258 0 : (void) sql_error(m, 02, "%s", err);
1259 0 : return -5;
1260 : }
1261 1326 : if (res == LOG_OK)
1262 1326 : res = sql_trans_set_partition_table(m->session->tr, *t);
1263 : }
1264 : return res;
1265 : }
1266 :
1267 : int
1268 22549 : mvc_create_view(sql_table **t, mvc *m, sql_schema *s, const char *name, int persistence, const char *sql, bit system)
1269 : {
1270 22549 : int res = LOG_OK;
1271 :
1272 22549 : TRC_DEBUG(SQL_TRANS, "Create view: %s %s %s\n", s->base.name, name, sql);
1273 22549 : if (persistence == SQL_DECLARED_TABLE) {
1274 22075 : *t = create_sql_table(m->store, m->sa, name, tt_view, system, persistence, 0, 0);
1275 22075 : (*t)->s = s;
1276 22075 : (*t)->query = sa_strdup(m->sa, sql);
1277 : } else {
1278 474 : res = sql_trans_create_table(t, m->session->tr, s, name, sql, tt_view, system, SQL_PERSIST, 0, 0, 0);
1279 : }
1280 22549 : return res;
1281 : }
1282 :
1283 : int
1284 93 : mvc_create_remote(sql_table **t, mvc *m, sql_schema *s, const char *name, int persistence, const char *loc)
1285 : {
1286 93 : int res = LOG_OK;
1287 :
1288 93 : TRC_DEBUG(SQL_TRANS, "Create remote: %s %s %s\n", s->base.name, name, loc);
1289 93 : if (persistence == SQL_DECLARED_TABLE) {
1290 93 : *t = create_sql_table(m->store, m->sa, name, tt_remote, 0, persistence, 0, 0);
1291 93 : (*t)->s = s;
1292 93 : (*t)->query = sa_strdup(m->sa, loc);
1293 : } else {
1294 0 : res = sql_trans_create_table(t, m->session->tr, s, name, loc, tt_remote, 0, SQL_REMOTE, 0, 0, 0);
1295 : }
1296 93 : return res;
1297 : }
1298 :
1299 : static str
1300 26 : remote_drop(mvc *m, sql_table *t)
1301 : {
1302 26 : sqlid id = t->base.id;
1303 26 : int log_res = 0;
1304 26 : sql_trans *tr = m->session->tr;
1305 26 : sqlstore *store = tr->store;
1306 26 : sql_schema *sys = find_sql_schema(tr, "sys");
1307 26 : sql_table *remote_user_info = find_sql_table(tr, sys, REMOTE_USER_INFO);
1308 26 : sql_column *remote_user_info_id = find_sql_column(remote_user_info, "table_id");
1309 26 : oid rid = store->table_api.column_find_row(tr, remote_user_info_id, &id, NULL);
1310 26 : if (is_oid_nil(rid)) {
1311 1 : TRC_WARNING(SQL_TRANS, "Drop table: %s %s no remote info\n", t->s->base.name, t->base.name);
1312 25 : } else if ((log_res = store->table_api.table_delete(tr, remote_user_info, rid)) != 0)
1313 0 : throw(SQL, "sql.drop_table", SQLSTATE(42000) "Drop table failed%s", log_res == LOG_CONFLICT ? " due to conflict with another transaction" : "");
1314 : return MAL_SUCCEED;
1315 : }
1316 :
1317 : str
1318 3789 : mvc_drop_table(mvc *m, sql_schema *s, sql_table *t, int drop_action)
1319 : {
1320 3789 : char *msg = NULL;
1321 3789 : TRC_DEBUG(SQL_TRANS, "Drop table: %s %s\n", s->base.name, t->base.name);
1322 :
1323 3789 : if (isRemote(t) && (msg = remote_drop(m, t)) != NULL)
1324 : return msg;
1325 :
1326 7139 : switch (sql_trans_drop_table(m->session->tr, s, t->base.name, drop_action ? DROP_CASCADE_START : DROP_RESTRICT)) {
1327 0 : case -1:
1328 0 : throw(SQL,"sql.mvc_drop_table",SQLSTATE(HY013) MAL_MALLOC_FAIL);
1329 0 : case -2:
1330 : case -3:
1331 0 : throw(SQL, "sql.mvc_drop_table", SQLSTATE(42000) "Transaction conflict while dropping table %s.%s", s->base.name, t->base.name);
1332 : default:
1333 : break;
1334 : }
1335 : return MAL_SUCCEED;
1336 : }
1337 :
1338 : BUN
1339 41809 : mvc_clear_table(mvc *m, sql_table *t)
1340 : {
1341 41809 : return sql_trans_clear_table(m->session->tr, t);
1342 : }
1343 :
1344 : int
1345 9807 : mvc_create_column_(sql_column **col, mvc *m, sql_table *t, const char *name, const char *type, unsigned int digits)
1346 : {
1347 9807 : sql_subtype tpe;
1348 :
1349 9807 : if (!sql_find_subtype(&tpe, type, digits, 0))
1350 : return -1;
1351 :
1352 9807 : return sql_trans_create_column(col, m->session->tr, t, name, &tpe);
1353 : }
1354 :
1355 : int
1356 250926 : mvc_create_column(sql_column **col, mvc *m, sql_table *t, const char *name, sql_subtype *tpe)
1357 : {
1358 250926 : int res = LOG_OK;
1359 :
1360 250926 : TRC_DEBUG(SQL_TRANS, "Create column: %s %s %s\n", t->base.name, name, tpe->type->base.name);
1361 250926 : if (t->persistence == SQL_DECLARED_TABLE)
1362 : /* declared tables should not end up in the catalog */
1363 250926 : *col = create_sql_column(m->store, m->sa, t, name, tpe);
1364 : else
1365 0 : res = sql_trans_create_column(col, m->session->tr, t, name, tpe);
1366 250926 : return res;
1367 : }
1368 :
1369 : int
1370 122 : mvc_drop_column(mvc *m, sql_table *t, sql_column *col, int drop_action)
1371 : {
1372 122 : TRC_DEBUG(SQL_TRANS, "Drop column: %s %s\n", t->base.name, col->base.name);
1373 122 : if (col->t->persistence == SQL_DECLARED_TABLE) {
1374 61 : drop_sql_column(t, col->base.id, drop_action);
1375 61 : return 0;
1376 : } else
1377 114 : return sql_trans_drop_column(m->session->tr, t, col->base.id, drop_action ? DROP_CASCADE_START : DROP_RESTRICT);
1378 : }
1379 :
1380 : int
1381 366104 : mvc_create_dependency(mvc *m, sql_base *b, sqlid depend_id, sql_dependency depend_type)
1382 : {
1383 366104 : int res = LOG_OK;
1384 :
1385 366104 : TRC_DEBUG(SQL_TRANS, "Create dependency: %d %d %d\n", b->id, depend_id, (int) depend_type);
1386 366104 : if ( (b->id != depend_id) || (depend_type == BEDROPPED_DEPENDENCY) ) {
1387 366103 : if (!b->new)
1388 220391 : res = sql_trans_add_dependency(m->session->tr, b->id, ddl);
1389 220391 : if (res == LOG_OK)
1390 366103 : res = sql_trans_create_dependency(m->session->tr, b->id, depend_id, depend_type);
1391 : }
1392 366104 : return res;
1393 : }
1394 :
1395 : int
1396 141372 : mvc_create_dependencies(mvc *m, list *blist, sqlid depend_id, sql_dependency dep_type)
1397 : {
1398 141372 : int res = LOG_OK;
1399 :
1400 141372 : TRC_DEBUG(SQL_TRANS, "Create dependencies on '%d' of type: %d\n", depend_id, (int) dep_type);
1401 141372 : if (!list_empty(blist)) {
1402 379311 : for (node *n = blist->h ; n && res == LOG_OK ; n = n->next) {
1403 352794 : sql_base *b = n->data;
1404 352794 : if (!b->new) /* only add old objects to the transaction dependency list */
1405 220341 : res = sql_trans_add_dependency(m->session->tr, b->id, ddl);
1406 352794 : if (res == LOG_OK)
1407 352794 : res = mvc_create_dependency(m, b, depend_id, dep_type);
1408 : }
1409 : }
1410 141372 : return res;
1411 : }
1412 :
1413 : int
1414 4458 : mvc_check_dependency(mvc *m, sqlid id, sql_dependency type, list *ignore_ids)
1415 : {
1416 4458 : list *dep_list = NULL;
1417 :
1418 4458 : TRC_DEBUG(SQL_TRANS, "Check dependency on: %d\n", id);
1419 4458 : switch (type) {
1420 89 : case OWNER_DEPENDENCY:
1421 89 : dep_list = sql_trans_owner_schema_dependencies(m->session->tr, id);
1422 89 : break;
1423 17 : case SCHEMA_DEPENDENCY:
1424 17 : dep_list = sql_trans_schema_user_dependencies(m->session->tr, id);
1425 17 : if (!dep_list)
1426 17 : dep_list = sql_trans_get_dependents(m->session->tr, id, SCHEMA_DEPENDENCY, NULL);
1427 : break;
1428 3070 : case TABLE_DEPENDENCY:
1429 3070 : dep_list = sql_trans_get_dependents(m->session->tr, id, TABLE_DEPENDENCY, NULL);
1430 3070 : break;
1431 363 : case VIEW_DEPENDENCY:
1432 363 : dep_list = sql_trans_get_dependents(m->session->tr, id, TABLE_DEPENDENCY, NULL);
1433 363 : break;
1434 656 : case FUNC_DEPENDENCY:
1435 : case PROC_DEPENDENCY:
1436 656 : dep_list = sql_trans_get_dependents(m->session->tr, id, FUNC_DEPENDENCY, ignore_ids);
1437 656 : break;
1438 263 : default:
1439 263 : dep_list = sql_trans_get_dependents(m->session->tr, id, COLUMN_DEPENDENCY, NULL);
1440 : }
1441 :
1442 4458 : if (!dep_list)
1443 : return DEPENDENCY_CHECK_ERROR;
1444 :
1445 4458 : if (list_length(dep_list) >= 2) {
1446 47 : list_destroy(dep_list);
1447 47 : return HAS_DEPENDENCY;
1448 : }
1449 :
1450 4411 : list_destroy(dep_list);
1451 4411 : return NO_DEPENDENCY;
1452 : }
1453 :
1454 : int
1455 16401 : mvc_null(mvc *m, sql_column *col, int isnull)
1456 : {
1457 16401 : TRC_DEBUG(SQL_TRANS, "Null: %s %d\n", col->base.name, isnull);
1458 16401 : if (col->t->persistence == SQL_DECLARED_TABLE) {
1459 16313 : col->null = isnull;
1460 16313 : return 0;
1461 : }
1462 88 : return sql_trans_alter_null(m->session->tr, col, isnull);
1463 : }
1464 :
1465 : int
1466 1398 : mvc_default(mvc *m, sql_column *col, char *val)
1467 : {
1468 1398 : TRC_DEBUG(SQL_TRANS, "Default: %s %s\n", col->base.name, val);
1469 1398 : if (col->t->persistence == SQL_DECLARED_TABLE) {
1470 1376 : col->def = val?sa_strdup(m->sa, val):NULL;
1471 1376 : return 0;
1472 : } else {
1473 22 : return sql_trans_alter_default(m->session->tr, col, val);
1474 : }
1475 : }
1476 :
1477 : int
1478 5 : mvc_drop_default(mvc *m, sql_column *col)
1479 : {
1480 5 : TRC_DEBUG(SQL_TRANS, "Drop default: %s\n", col->base.name);
1481 5 : if (col->t->persistence == SQL_DECLARED_TABLE) {
1482 5 : col->def = NULL;
1483 5 : return 0;
1484 : } else {
1485 0 : return sql_trans_alter_default(m->session->tr, col, NULL);
1486 : }
1487 : }
1488 :
1489 : int
1490 0 : mvc_storage(mvc *m, sql_column *col, char *storage)
1491 : {
1492 0 : TRC_DEBUG(SQL_TRANS, "Storage: %s %s\n", col->base.name, storage);
1493 0 : if (col->t->persistence == SQL_DECLARED_TABLE) {
1494 0 : col->storage_type = storage?sa_strdup(m->sa, storage):NULL;
1495 0 : return 0;
1496 : } else {
1497 0 : return sql_trans_alter_storage(m->session->tr, col, storage);
1498 : }
1499 : }
1500 :
1501 : int
1502 2036 : mvc_access(mvc *m, sql_table *t, sht access)
1503 : {
1504 2036 : TRC_DEBUG(SQL_TRANS, "Access: %s %d\n", t->base.name, access);
1505 2036 : if (t->persistence == SQL_DECLARED_TABLE) {
1506 0 : t->access = access;
1507 0 : return 0;
1508 : }
1509 2036 : return sql_trans_alter_access(m->session->tr, t, access);
1510 : }
1511 :
1512 : int
1513 26283 : mvc_is_sorted(mvc *m, sql_column *col)
1514 : {
1515 26283 : TRC_DEBUG(SQL_TRANS, "Is sorted: %s\n", col->base.name);
1516 26283 : return sql_trans_is_sorted(m->session->tr, col);
1517 : }
1518 :
1519 : int
1520 7230 : mvc_is_unique(mvc *m, sql_column *col)
1521 : {
1522 7230 : TRC_DEBUG(SQL_TRANS, "Is unique: %s\n", col->base.name);
1523 7230 : return sql_trans_is_unique(m->session->tr, col);
1524 : }
1525 :
1526 : int
1527 1716 : mvc_is_duplicate_eliminated(mvc *m, sql_column *col)
1528 : {
1529 1716 : TRC_DEBUG(SQL_TRANS, "Is duplicate eliminated: %s\n", col->base.name);
1530 1716 : return sql_trans_is_duplicate_eliminated(m->session->tr, col);
1531 : }
1532 :
1533 : int
1534 4004451 : mvc_col_stats(mvc *m, sql_column *col, bool *nonil, bool *unique, double *unique_est, ValPtr min, ValPtr max)
1535 : {
1536 4004451 : TRC_DEBUG(SQL_TRANS, "Retrieving column stats for: %s\n", col->base.name);
1537 4004451 : return sql_trans_col_stats(m->session->tr, col, nonil, unique, unique_est, min, max);
1538 : }
1539 :
1540 : int
1541 250524 : mvc_copy_column(mvc *m, sql_table *t, sql_column *c, sql_column **cres)
1542 : {
1543 250524 : return sql_trans_copy_column(m->session->tr, t, c, cres);
1544 : }
1545 :
1546 : int
1547 6572 : mvc_copy_key(mvc *m, sql_table *t, sql_key *k, sql_key **kres)
1548 : {
1549 6572 : return sql_trans_copy_key(m->session->tr, t, k, kres);
1550 : }
1551 :
1552 : int
1553 6893 : mvc_copy_idx(mvc *m, sql_table *t, sql_idx *i, sql_idx **ires)
1554 : {
1555 6893 : return sql_trans_copy_idx(m->session->tr, t, i, ires);
1556 : }
1557 :
1558 : int
1559 0 : mvc_copy_trigger(mvc *m, sql_table *t, sql_trigger *tr, sql_trigger **tres)
1560 : {
1561 0 : return sql_trans_copy_trigger(m->session->tr, t, tr, tres);
1562 : }
1563 :
1564 : sql_rel *
1565 698837 : sql_processrelation(mvc *sql, sql_rel *rel, int profile, int instantiate, int value_based_opt, int storage_based_opt)
1566 : {
1567 698837 : int emode = sql->emode;
1568 698837 : if (!instantiate)
1569 140381 : sql->emode = m_deps;
1570 698837 : if (rel)
1571 698837 : rel = rel_unnest(sql, rel);
1572 699371 : sql->emode = emode;
1573 699371 : if (rel)
1574 699355 : rel = rel_optimizer(sql, rel, profile, instantiate, value_based_opt, storage_based_opt);
1575 699341 : return rel;
1576 : }
1577 :
1578 : static inline int dlist_cmp(mvc *sql, dlist *l1, dlist *l2);
1579 :
1580 : static inline int
1581 485 : dnode_cmp(mvc *sql, dnode *d1, dnode *d2)
1582 : {
1583 485 : if (d1 == d2)
1584 : return 0;
1585 :
1586 485 : if (!d1 || !d2)
1587 : return -1;
1588 :
1589 485 : if (d1->type == d2->type) {
1590 485 : switch (d1->type) {
1591 39 : case type_int:
1592 39 : return (d1->data.i_val - d2->data.i_val);
1593 0 : case type_lng: {
1594 0 : lng c = d1->data.l_val - d2->data.l_val;
1595 0 : assert((lng) GDK_int_min <= c && c <= (lng) GDK_int_max);
1596 0 : return (int) c;
1597 : }
1598 249 : case type_string:
1599 249 : if (d1->data.sval == d2->data.sval)
1600 : return 0;
1601 249 : if (!d1->data.sval || !d2->data.sval)
1602 : return -1;
1603 249 : return strcmp(d1->data.sval, d2->data.sval);
1604 99 : case type_list:
1605 99 : return dlist_cmp(sql, d1->data.lval, d2->data.lval);
1606 98 : case type_symbol:
1607 98 : return symbol_cmp(sql, d1->data.sym, d2->data.sym);
1608 0 : case type_type:
1609 0 : return subtype_cmp(&d1->data.typeval, &d2->data.typeval);
1610 : default:
1611 0 : assert(0);
1612 : }
1613 : }
1614 : return -1;
1615 : }
1616 :
1617 : static inline int
1618 352 : dlist_cmp(mvc *sql, dlist *l1, dlist *l2)
1619 : {
1620 352 : int res = 0;
1621 352 : dnode *d1, *d2;
1622 :
1623 352 : if (l1 == l2)
1624 : return 0;
1625 :
1626 352 : if (!l1 || !l2 || dlist_length(l1) != dlist_length(l2))
1627 28 : return -1;
1628 :
1629 809 : for (d1 = l1->h, d2 = l2->h; !res && d1; d1 = d1->next, d2 = d2->next) {
1630 485 : res = dnode_cmp(sql, d1, d2);
1631 : }
1632 : return res;
1633 : }
1634 :
1635 : static inline int
1636 125 : AtomNodeCmp(AtomNode *a1, AtomNode *a2)
1637 : {
1638 125 : if (a1 == a2)
1639 : return 0;
1640 125 : if (!a1 || !a2)
1641 : return -1;
1642 125 : if (a1->a && a2->a)
1643 125 : return atom_cmp(a1->a, a2->a);
1644 : return -1;
1645 : }
1646 :
1647 : static inline int
1648 0 : SelectNodeCmp(mvc *sql, SelectNode *s1, SelectNode *s2)
1649 : {
1650 0 : if (s1 == s2)
1651 : return 0;
1652 0 : if (!s1 || !s2)
1653 : return -1;
1654 :
1655 0 : if (symbol_cmp(sql, s1->limit, s2->limit) == 0 &&
1656 0 : symbol_cmp(sql, s1->offset, s2->offset) == 0 &&
1657 0 : symbol_cmp(sql, s1->sample, s2->sample) == 0 &&
1658 0 : symbol_cmp(sql, s1->seed, s2->seed) == 0 &&
1659 0 : s1->distinct == s2->distinct &&
1660 0 : s1->lateral == s2->lateral &&
1661 0 : symbol_cmp(sql, s1->name, s2->name) == 0 &&
1662 0 : symbol_cmp(sql, s1->orderby, s2->orderby) == 0 &&
1663 0 : symbol_cmp(sql, s1->having, s2->having) == 0 &&
1664 0 : symbol_cmp(sql, s1->groupby, s2->groupby) == 0 &&
1665 0 : symbol_cmp(sql, s1->where, s2->where) == 0 &&
1666 0 : symbol_cmp(sql, s1->from, s2->from) == 0 &&
1667 0 : symbol_cmp(sql, s1->window, s2->window) == 0 &&
1668 0 : dlist_cmp(sql, s1->selection, s2->selection) == 0)
1669 : return 0;
1670 : return -1;
1671 : }
1672 :
1673 : static inline int
1674 396 : _symbol_cmp(mvc *sql, symbol *s1, symbol *s2)
1675 : {
1676 396 : if (s1 == s2)
1677 : return 0;
1678 396 : if (!s1 || !s2)
1679 : return -1;
1680 396 : if (s1->token != s2->token || s1->type != s2->type)
1681 : return -1;
1682 380 : switch (s1->type) {
1683 0 : case type_int:
1684 0 : return (s1->data.i_val - s2->data.i_val);
1685 0 : case type_lng: {
1686 0 : lng c = s1->data.l_val - s2->data.l_val;
1687 0 : assert((lng) GDK_int_min <= c && c <= (lng) GDK_int_max);
1688 0 : return (int) c;
1689 : }
1690 2 : case type_string:
1691 2 : if (s1->data.sval == s2->data.sval)
1692 : return 0;
1693 0 : if (!s1->data.sval || !s2->data.sval)
1694 : return -1;
1695 0 : return strcmp(s1->data.sval, s2->data.sval);
1696 253 : case type_list: {
1697 253 : return dlist_cmp(sql, s1->data.lval, s2->data.lval);
1698 : }
1699 0 : case type_type:
1700 0 : return subtype_cmp(&s1->data.typeval, &s2->data.typeval);
1701 125 : case type_symbol:
1702 125 : if (s1->token == SQL_SELECT) {
1703 0 : if (s2->token != SQL_SELECT)
1704 : return -1;
1705 0 : return SelectNodeCmp(sql, (SelectNode *) s1, (SelectNode *) s2);
1706 125 : } else if (s1->token == SQL_ATOM) {
1707 125 : if (s2->token != SQL_ATOM)
1708 : return -1;
1709 125 : return AtomNodeCmp((AtomNode *) s1, (AtomNode *) s2);
1710 : } else {
1711 0 : return symbol_cmp(sql, s1->data.sym, s2->data.sym);
1712 : }
1713 : default:
1714 0 : assert(0);
1715 : }
1716 : return 0; /* never reached, just to pacify compilers */
1717 : }
1718 :
1719 : int
1720 396 : symbol_cmp(mvc *sql, symbol *s1, symbol *s2)
1721 : {
1722 396 : return _symbol_cmp(sql, s1, s2);
1723 : }
|