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 : #include "monetdb_config.h"
14 : #include "sql_types.h"
15 : #include "sql_storage.h"
16 : #include "store_dependency.h"
17 : #include "store_sequence.h"
18 : #include "mutils.h"
19 : #include "sql_keyword.h"
20 :
21 : #include "bat/bat_utils.h"
22 : #include "bat/bat_storage.h"
23 : #include "bat/bat_table.h"
24 : #include "bat/bat_logger.h"
25 :
26 : /* version 05.23.04 of catalog */
27 : #define CATALOG_VERSION 52304 /* first after Aug2024 */
28 :
29 : ulng
30 308 : store_function_counter(sqlstore *store)
31 : {
32 308 : ulng ts = ATOMIC_INC(&store->function_counter);
33 308 : return ts;
34 : }
35 :
36 : static ulng
37 374561 : store_timestamp(sqlstore *store)
38 : {
39 374561 : ulng ts = ATOMIC_INC(&store->timestamp);
40 374561 : return ts;
41 : }
42 :
43 : ulng
44 444034 : store_get_timestamp(sqlstore *store)
45 : {
46 444034 : ulng ts = ATOMIC_GET(&store->timestamp);
47 444034 : return ts;
48 : }
49 :
50 : static ulng
51 38412 : store_transaction_id(sqlstore *store)
52 : {
53 38412 : ulng tid = ATOMIC_INC(&store->transaction);
54 38412 : return tid;
55 : }
56 :
57 : ulng
58 2298541 : store_oldest(sqlstore *store, sql_trans *tr)
59 : {
60 2298541 : if (tr && tr->ts == (ulng) ATOMIC_GET(&store->oldest)) {
61 44582 : sql_trans *otr = store->active->h->data;
62 44582 : if (otr == tr && store->active->h->next) {
63 37040 : otr = store->active->h->next->data;
64 37040 : return otr->ts;
65 : }
66 : }
67 2261501 : return (ulng) ATOMIC_GET(&store->oldest);
68 : }
69 :
70 : static ulng
71 1615 : store_oldest_pending(sqlstore *store)
72 : {
73 1615 : assert(store->oldest_pending != TRANSACTION_ID_BASE);
74 1615 : return store->oldest_pending;
75 : }
76 :
77 : static inline bool
78 178144 : instore(sqlid id)
79 : {
80 249 : if (id >= 2000 && id <= 2172)
81 19431 : return true;
82 : return false;
83 : }
84 :
85 : static void
86 1577 : id_destroy(sqlstore *store, void *p)
87 : {
88 1577 : (void)store;
89 1577 : GDKfree(p);
90 1577 : }
91 :
92 : static void
93 767512 : dep_destroy(sqlstore *store, sql_dependency_change *dep)
94 : {
95 767512 : (void)store;
96 767512 : GDKfree(dep);
97 767576 : }
98 :
99 : static void
100 1514 : type_destroy(sqlstore *store, sql_type *t)
101 : {
102 1514 : (void)store;
103 1514 : assert(t->base.refcnt > 0);
104 1514 : if (ATOMIC_DEC(&t->base.refcnt) > 0)
105 : return;
106 1475 : if (!t->composite)
107 1438 : _DELETE(t->d.impl);
108 : else
109 37 : list_destroy(t->d.fields);
110 1475 : _DELETE(t->base.name);
111 1475 : _DELETE(t);
112 : }
113 :
114 : void
115 548142 : arg_destroy(sql_store store, sql_arg *a)
116 : {
117 548142 : (void)store;
118 548142 : _DELETE(a->name);
119 548142 : _DELETE(a);
120 548142 : }
121 :
122 : static void
123 191997 : func_destroy(sqlstore *store, sql_func *f)
124 : {
125 191997 : assert(f->base.refcnt > 0);
126 191997 : if (ATOMIC_DEC(&f->base.refcnt) > 0)
127 : return;
128 191261 : if (f->lang == FUNC_LANG_SQL && f->instantiated) {
129 : /* clean backend code */
130 306 : backend_freecode(sql_shared_module_name, 0, f->imp);
131 : }
132 191261 : if (f->res)
133 161448 : list_destroy2(f->res, store);
134 191261 : list_destroy2(f->ops, store);
135 191261 : _DELETE(f->imp);
136 191261 : _DELETE(f->mod);
137 191261 : _DELETE(f->query);
138 191261 : _DELETE(f->base.name);
139 191261 : _DELETE(f);
140 : }
141 :
142 : static void
143 590 : seq_destroy(sqlstore *store, sql_sequence *s)
144 : {
145 590 : (void)store;
146 590 : assert(s->base.refcnt > 0);
147 590 : if (ATOMIC_DEC(&s->base.refcnt) > 0)
148 : return;
149 383 : _DELETE(s->base.name);
150 383 : _DELETE(s);
151 : }
152 :
153 : static void
154 26990 : kc_destroy(sqlstore *store, sql_kc *kc)
155 : {
156 26990 : (void)store;
157 26990 : _DELETE(kc);
158 26990 : }
159 :
160 : static void
161 38094 : key_destroy(sqlstore *store, sql_key *k)
162 : {
163 38094 : assert(k->base.refcnt > 0);
164 38094 : if (ATOMIC_DEC(&k->base.refcnt) > 0)
165 : return;
166 11478 : list_destroy2(k->columns, store);
167 11478 : _DELETE(k->check);
168 11478 : k->columns = NULL;
169 11478 : _DELETE(k->base.name);
170 11478 : _DELETE(k);
171 : }
172 :
173 : void
174 31088 : idx_destroy(sqlstore *store, sql_idx * i)
175 : {
176 31088 : assert(i->base.refcnt > 0);
177 31088 : if (ATOMIC_DEC(&i->base.refcnt) > 0)
178 : return;
179 13212 : list_destroy2(i->columns, store);
180 13212 : i->columns = NULL;
181 :
182 13212 : if (ATOMIC_PTR_GET(&i->data))
183 11618 : store->storage_api.destroy_idx(store, i);
184 13212 : _DELETE(i->base.name);
185 13212 : _DELETE(i);
186 : }
187 :
188 : static void
189 1086 : trigger_destroy(sqlstore *store, sql_trigger *t)
190 : {
191 1086 : assert(t->base.refcnt > 0);
192 1086 : if (ATOMIC_DEC(&t->base.refcnt) > 0)
193 : return;
194 : /* remove trigger from schema */
195 495 : if (t->columns) {
196 491 : list_destroy2(t->columns, store);
197 491 : t->columns = NULL;
198 : }
199 495 : _DELETE(t->old_name);
200 495 : _DELETE(t->new_name);
201 495 : _DELETE(t->condition);
202 495 : _DELETE(t->statement);
203 495 : _DELETE(t->base.name);
204 495 : _DELETE(t);
205 : }
206 :
207 : void
208 527035 : column_destroy(sqlstore *store, sql_column *c)
209 : {
210 527035 : assert(c->base.refcnt > 0);
211 527035 : if (ATOMIC_DEC(&c->base.refcnt) > 0)
212 : return;
213 507252 : if (ATOMIC_PTR_GET(&c->data))
214 181740 : store->storage_api.destroy_col(store, c);
215 507252 : _DELETE(c->min);
216 507252 : _DELETE(c->max);
217 507252 : _DELETE(c->def);
218 507252 : _DELETE(c->storage_type);
219 507252 : _DELETE(c->base.name);
220 507252 : _DELETE(c);
221 : }
222 :
223 : static void
224 95 : int_destroy(sqlstore *store, int *v)
225 : {
226 95 : (void)store;
227 95 : _DELETE(v);
228 95 : }
229 :
230 : void
231 318151 : table_destroy(sqlstore *store, sql_table *t)
232 : {
233 318151 : assert(t->base.refcnt > 0);
234 318151 : if (ATOMIC_DEC(&t->base.refcnt) > 0)
235 : return;
236 65352 : if (isTable(t))
237 28365 : store->storage_api.destroy_del(store, t);
238 : /* cleanup its parts */
239 65352 : list_destroy2(t->members, store);
240 65352 : ol_destroy(t->idxs, store);
241 65352 : ol_destroy(t->keys, store);
242 65352 : ol_destroy(t->triggers, store);
243 65352 : ol_destroy(t->columns, store);
244 65352 : if (isPartitionedByExpressionTable(t)) {
245 86 : if (t->part.pexp->cols)
246 86 : list_destroy2(t->part.pexp->cols, store);
247 86 : _DELETE(t->part.pexp->exp);
248 86 : _DELETE(t->part.pexp);
249 : }
250 65352 : _DELETE(t->query);
251 65352 : _DELETE(t->base.name);
252 65352 : _DELETE(t);
253 : }
254 :
255 : void
256 441 : part_value_destroy(sql_store store, sql_part_value *pv)
257 : {
258 441 : (void)store;
259 441 : _DELETE(pv->value);
260 441 : _DELETE(pv);
261 441 : }
262 :
263 : static void
264 2774 : part_destroy(sqlstore *store, sql_part *p)
265 : {
266 2774 : assert(p->base.refcnt > 0);
267 2774 : if (ATOMIC_DEC(&p->base.refcnt) > 0)
268 : return;
269 1262 : if (p->part.range.maxvalue) {
270 522 : _DELETE(p->part.range.minvalue);
271 522 : _DELETE(p->part.range.maxvalue);
272 740 : } else if (p->part.values)
273 147 : list_destroy2(p->part.values, store);
274 1262 : _DELETE(p->base.name);
275 1262 : _DELETE(p);
276 : }
277 :
278 : static void
279 2983 : schema_destroy(sqlstore *store, sql_schema *s)
280 : {
281 2983 : assert(s->base.refcnt > 0);
282 2983 : if (ATOMIC_DEC(&s->base.refcnt) > 0)
283 : return;
284 : /* cleanup its parts */
285 2782 : os_destroy(s->parts, store);
286 2782 : os_destroy(s->triggers, store);
287 2782 : os_destroy(s->idxs, store);
288 2782 : os_destroy(s->keys, store);
289 2782 : os_destroy(s->seqs, store);
290 2782 : os_destroy(s->tables, store);
291 2782 : os_destroy(s->funcs, store);
292 2782 : os_destroy(s->types, store);
293 2782 : _DELETE(s->base.name);
294 2782 : _DELETE(s);
295 : }
296 :
297 : static void
298 21170 : predicate_destroy(sqlstore *store, pl *p)
299 : {
300 21170 : (void) store;
301 21170 : if (p->r) {
302 2026 : VALclear(&p->r->data);
303 2026 : _DELETE(p->r);
304 : }
305 21170 : if (p->f) {
306 11 : VALclear(&p->f->data);
307 11 : _DELETE(p->f);
308 : }
309 21170 : _DELETE(p);
310 21170 : }
311 :
312 : int
313 21164 : sql_trans_add_predicate(sql_trans* tr, sql_column *c, unsigned int cmp, atom *r, atom *f, bool anti, bool semantics)
314 : {
315 21164 : pl *p = ZNEW(pl);
316 :
317 21170 : if (!p)
318 : return LOG_ERR;
319 21170 : p->c = c;
320 21170 : p->cmp = cmp;
321 21170 : p->anti = anti;
322 21170 : p->semantics = semantics;
323 21170 : p->r = r;
324 21170 : p->f = f;
325 21170 : if (!tr->predicates && !(tr->predicates = list_create((fdestroy) &predicate_destroy))) {
326 0 : predicate_destroy(tr->store, p);
327 0 : return LOG_ERR;
328 : }
329 21170 : if (!list_append(tr->predicates, p)) {
330 0 : predicate_destroy(tr->store, p);
331 0 : return LOG_ERR;
332 : }
333 : return LOG_OK;
334 : }
335 :
336 : int
337 607793 : sql_trans_add_dependency(sql_trans* tr, sqlid id, sql_dependency_change_type tp)
338 : {
339 607793 : sql_dependency_change *dep = MNEW(sql_dependency_change);
340 :
341 607793 : if (!dep)
342 : return LOG_ERR;
343 607793 : *dep = (sql_dependency_change) {
344 : .objid = id,
345 : .type = tp
346 : };
347 607793 : if (!tr->dependencies && !(tr->dependencies = list_create((fdestroy) &dep_destroy))) {
348 0 : _DELETE(dep);
349 0 : return LOG_ERR;
350 : }
351 607793 : if (!list_append(tr->dependencies, dep)) {
352 0 : _DELETE(dep);
353 0 : return LOG_ERR;
354 : }
355 : return LOG_OK;
356 : }
357 :
358 : int
359 159228 : sql_trans_add_dependency_change(sql_trans *tr, sqlid id, sql_dependency_change_type tp)
360 : {
361 159228 : sql_dependency_change *dep = MNEW(sql_dependency_change);
362 :
363 159722 : if (!dep)
364 : return LOG_ERR;
365 159722 : *dep = (sql_dependency_change) {
366 : .objid = id,
367 : .type = tp
368 : };
369 159722 : if (!tr->depchanges && !(tr->depchanges = list_create((fdestroy) &dep_destroy))) {
370 0 : _DELETE(dep);
371 0 : return LOG_ERR;
372 : }
373 159729 : if (!list_append(tr->depchanges, dep)) {
374 0 : _DELETE(dep);
375 0 : return LOG_ERR;
376 : }
377 : return LOG_OK;
378 : }
379 :
380 : static void
381 2509 : load_keycolumn(sql_trans *tr, sql_key *k, res_table *rt_keycols/*, oid rid*/)
382 : {
383 2509 : sql_kc *kc = ZNEW(sql_kc);
384 2509 : sql_schema *syss = find_sql_schema(tr, "sys");
385 2509 : sql_table *objects = find_sql_table(tr, syss, "objects");
386 2509 : sqlstore *store = tr->store;
387 :
388 2509 : str v = (char*)store->table_api.table_fetch_value(rt_keycols, find_sql_column(objects, "name"));
389 2509 : kc->c = find_sql_column(k->t, v);
390 2509 : list_append(k->columns, kc);
391 2509 : assert(kc->c);
392 2509 : }
393 :
394 : static sql_key *
395 2468 : load_key(sql_trans *tr, sql_table *t, res_table *rt_keys, res_table *rt_keycols/*, oid rid*/)
396 : {
397 2468 : sql_schema *syss = find_sql_schema(tr, "sys");
398 2468 : sql_table *keys = find_sql_table(tr, syss, "keys");
399 2468 : sql_table *objects = find_sql_table(tr, syss, "objects");
400 2468 : sqlstore *store = tr->store;
401 :
402 2468 : key_type ktype = (key_type) *(int*) store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "type"));
403 2468 : sql_key *nk = (ktype != fkey)?(sql_key*)ZNEW(sql_ukey):(sql_key*)ZNEW(sql_fkey);
404 2468 : sqlid kid = *(sqlid*) store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "id"));
405 2468 : str v = (char*) store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "name"));
406 :
407 2468 : base_init(NULL, &nk->base, kid, 0, v);
408 2468 : nk->type = ktype;
409 2468 : nk->columns = list_create((fdestroy) &kc_destroy);
410 2468 : nk->t = t;
411 :
412 2468 : switch (ktype) {
413 6 : case ckey: {
414 6 : str ch = (char*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "check"));
415 12 : if (!strNil(ch))
416 6 : nk->check =_STRDUP(ch);
417 : } break;
418 2426 : case ukey:
419 : case unndkey:
420 : case pkey: {
421 2426 : sql_ukey *uk = (sql_ukey *) nk;
422 :
423 2426 : if (ktype == pkey)
424 1501 : t->pkey = uk;
425 : break;
426 : }
427 36 : case fkey: {
428 36 : sql_fkey *fk = (sql_fkey *) nk;
429 36 : int action = *(int*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "action"));
430 36 : fk->on_delete = action & 255;
431 36 : fk->on_update = (action>>8) & 255;
432 :
433 36 : fk->rkey = *(sqlid*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "rkey"));
434 36 : break;
435 : }
436 : }
437 :
438 4977 : for ( ; rt_keycols->cur_row < rt_keycols->nr_rows; rt_keycols->cur_row++) {
439 4850 : sqlid nid = *(sqlid*)store->table_api.table_fetch_value(rt_keycols, find_sql_column(objects, "id"));
440 4850 : if (nid != nk->base.id)
441 : break;
442 2509 : load_keycolumn(tr, nk, rt_keycols);
443 : }
444 :
445 : /* find idx with same name */
446 2468 : node *n = ol_find_name(t->idxs, nk->base.name);
447 2468 : if (n) {
448 2462 : nk->idx = (sql_idx*)n->data;
449 2462 : nk->idx->key = nk;
450 : }
451 2468 : return nk;
452 : }
453 :
454 : static void
455 2545 : load_idxcolumn(sql_trans *tr, sql_idx * i, res_table *rt_idxcols/*, oid rid*/)
456 : {
457 2545 : sql_kc *kc = ZNEW(sql_kc);
458 2545 : sql_schema *syss = find_sql_schema(tr, "sys");
459 2545 : sql_table *objects = find_sql_table(tr, syss, "objects");
460 2545 : sqlstore *store = tr->store;
461 2545 : str v;
462 :
463 2545 : v = (char*)store->table_api.table_fetch_value(rt_idxcols, find_sql_column(objects, "name"));
464 2545 : kc->c = find_sql_column(i->t, v);
465 2545 : assert(kc->c);
466 2545 : list_append(i->columns, kc);
467 2545 : }
468 :
469 : static sql_idx *
470 2494 : load_idx(sql_trans *tr, sql_table *t, res_table *rt_idx, res_table *rt_idxcols/*, oid rid*/)
471 : {
472 2494 : sql_idx *ni = ZNEW(sql_idx);
473 2494 : sql_schema *syss = find_sql_schema(tr, "sys");
474 2494 : sql_table *idxs = find_sql_table(tr, syss, "idxs");
475 2494 : sql_table *objects = find_sql_table(tr, syss, "objects");
476 2494 : sqlstore *store = tr->store;
477 :
478 2494 : sqlid iid = *(sqlid*)store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "id"));
479 2494 : str v = (char*)store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "name"));
480 2494 : base_init(NULL, &ni->base, iid, 0, v);
481 2494 : ni->type = (idx_type) *(int*) store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "type"));
482 2494 : ni->columns = list_create((fdestroy) &kc_destroy);
483 2494 : ni->t = t;
484 2494 : ni->key = NULL;
485 2494 : ATOMIC_PTR_INIT(&ni->data, NULL);
486 :
487 2494 : if (isTable(ni->t) && idx_has_column(ni->type))
488 2442 : store->storage_api.create_idx(tr, ni);
489 :
490 5039 : for ( ; rt_idxcols->cur_row < rt_idxcols->nr_rows; rt_idxcols->cur_row++) {
491 4912 : sqlid nid = *(sqlid*)store->table_api.table_fetch_value(rt_idxcols, find_sql_column(objects, "id"));
492 4912 : if (nid != ni->base.id)
493 : break;
494 2545 : load_idxcolumn(tr, ni, rt_idxcols);
495 : }
496 2494 : return ni;
497 : }
498 :
499 : static void
500 0 : load_triggercolumn(sql_trans *tr, sql_trigger * i, res_table *rt_triggercols)
501 : {
502 0 : sql_kc *kc = ZNEW(sql_kc);
503 0 : sql_schema *syss = find_sql_schema(tr, "sys");
504 0 : sql_table *objects = find_sql_table(tr, syss, "objects");
505 0 : sqlstore *store = tr->store;
506 :
507 0 : str v = (char*)store->table_api.table_fetch_value(rt_triggercols, find_sql_column(objects, "name"));
508 0 : kc->c = find_sql_column(i->t, v);
509 0 : list_append(i->columns, kc);
510 0 : assert(kc->c);
511 0 : }
512 :
513 : static sql_trigger *
514 19 : load_trigger(sql_trans *tr, sql_table *t, res_table *rt_triggers, res_table *rt_triggercols)
515 : {
516 19 : sql_trigger *nt = ZNEW(sql_trigger);
517 19 : sql_schema *syss = find_sql_schema(tr, "sys");
518 19 : sql_table *triggers = find_sql_table(tr, syss, "triggers");
519 19 : sql_table *objects = find_sql_table(tr, syss, "objects");
520 19 : sqlstore *store = tr->store;
521 :
522 19 : sqlid tid = *(sqlid*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "id"));
523 19 : str v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "name"));
524 19 : base_init(NULL, &nt->base, tid, 0, v);
525 :
526 19 : nt->time = *(sht*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "time"));
527 19 : nt->orientation = *(sht*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "orientation"));
528 19 : nt->event = *(sht*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "event"));
529 :
530 19 : v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "old_name"));
531 38 : if (!strNil(v))
532 0 : nt->old_name =_STRDUP(v);
533 19 : v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "new_name"));
534 38 : if (!strNil(v))
535 19 : nt->new_name =_STRDUP(v);
536 19 : v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "condition"));
537 38 : if (!strNil(v))
538 0 : nt->condition =_STRDUP(v);
539 19 : v = (char*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "statement"));
540 38 : if (!strNil(v))
541 19 : nt->statement =_STRDUP(v);
542 :
543 19 : nt->t = t;
544 19 : if (t)
545 19 : nt->columns = list_create((fdestroy) &kc_destroy);
546 :
547 19 : if (rt_triggercols) {
548 19 : for ( ; rt_triggercols->cur_row < rt_triggercols->nr_rows; rt_triggercols->cur_row++) {
549 0 : sqlid nid = *(sqlid*)store->table_api.table_fetch_value(rt_triggercols, find_sql_column(objects, "id"));
550 0 : if (nid != nt->base.id)
551 : break;
552 0 : load_triggercolumn(tr, nt, rt_triggercols);
553 : }
554 : }
555 19 : return nt;
556 : }
557 :
558 : static sql_column *
559 122745 : load_column(sql_trans *tr, sql_table *t, res_table *rt_cols)
560 : {
561 122745 : sql_column *c = ZNEW(sql_column);
562 122745 : sql_schema *syss = find_sql_schema(tr, "sys");
563 122745 : sql_table *columns = find_sql_table(tr, syss, "_columns");
564 122745 : sqlstore *store = tr->store;
565 122745 : str v, def, tpe, st;
566 122745 : int sz, d;
567 :
568 122745 : sqlid cid = *(sqlid*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "id"));
569 122745 : v = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "name"));
570 122745 : base_init(NULL, &c->base, cid, 0, v);
571 :
572 122745 : sz = *(int*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "type_digits"));
573 122745 : d = *(int*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "type_scale"));
574 122745 : tpe = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "type"));
575 122745 : if (tpe && strcmp(tpe, "clob") == 0)
576 610 : tpe = "varchar";
577 122745 : if (!sql_find_subtype(&c->type, tpe, sz, d)) {
578 30 : sql_type *lt = sql_trans_bind_type(tr, t->s, tpe);
579 30 : if (lt == NULL) {
580 0 : TRC_ERROR(SQL_STORE, "SQL type '%s' is missing\n", tpe);
581 0 : return NULL;
582 : }
583 30 : sql_init_subtype(&c->type, lt, sz, d);
584 : }
585 122745 : c->type.multiset = *(bte*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "multiset"));
586 122745 : c->def = NULL;
587 122745 : def = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "default"));
588 245490 : if (!strNil(def))
589 300 : c->def =_STRDUP(def);
590 122745 : c->null = *(bit*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "null"));
591 122745 : c->colnr = *(int*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "number"));
592 122745 : c->unique = 0;
593 122745 : c->storage_type = NULL;
594 122745 : st = (char*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "storage"));
595 245490 : if (!strNil(st))
596 4 : c->storage_type =_STRDUP(st);
597 122745 : c->column_type = *(bte*)store->table_api.table_fetch_value(rt_cols, find_sql_column(columns, "column_type"));
598 122745 : ATOMIC_PTR_INIT(&c->data, NULL);
599 122745 : c->t = t;
600 122745 : if (isTable(c->t) && (c->type.multiset || !c->type.type->composite))
601 12345 : store->storage_api.create_col(tr, c);
602 122745 : TRC_DEBUG(SQL_STORE, "Load column: %s\n", c->base.name);
603 122745 : if (!c->null)
604 4342 : store->storage_api.col_not_null(tr, c, !c->null);
605 : return c;
606 : }
607 :
608 : static int
609 268 : col_set_range(sql_trans *tr, sql_part *pt, bool add_range)
610 : {
611 268 : sql_table *t = find_sql_table_id(tr, pt->t->s /* schema of both member and merge tbale */, pt->member);
612 268 : sql_column *c = t? find_sql_column(t, pt->t->part.pcol->base.name):NULL;
613 :
614 268 : if (c) {
615 257 : sqlstore *store = tr->store;
616 257 : return store->storage_api.col_set_range(tr, c, pt, add_range);
617 : }
618 : return 0;
619 : }
620 :
621 : static int
622 78 : load_range_partition(sql_trans *tr, sql_schema *syss, sql_part *pt)
623 : {
624 78 : oid rid;
625 78 : rids *rs;
626 78 : sqlstore *store = tr->store;
627 78 : sql_table *ranges = find_sql_table(tr, syss, "range_partitions");
628 78 : assert(ranges);
629 :
630 78 : rs = store->table_api.rids_select(tr, find_sql_column(ranges, "table_id"), &pt->member, &pt->member, NULL);
631 78 : if (rs == NULL)
632 : return -1;
633 78 : if ((rid = store->table_api.rids_next(rs)) != oid_nil) {
634 78 : ptr cbat;
635 78 : const char *v;
636 :
637 78 : pt->with_nills = (bit) store->table_api.column_find_bte(tr, find_sql_column(ranges, "with_nulls"), rid);
638 78 : v = store->table_api.column_find_string_start(tr, find_sql_column(ranges, "minimum"), rid, &cbat);
639 78 : pt->part.range.minvalue =_STRDUP(v);
640 78 : pt->part.range.minlength = strLen(v);
641 78 : store->table_api.column_find_string_end(cbat);
642 78 : v = store->table_api.column_find_string_start(tr, find_sql_column(ranges, "maximum"), rid, &cbat);
643 78 : pt->part.range.maxvalue =_STRDUP(v);
644 78 : pt->part.range.maxlength = strLen(v);
645 78 : store->table_api.column_find_string_end(cbat);
646 : }
647 78 : store->table_api.rids_destroy(rs);
648 78 : return 0;
649 : }
650 :
651 : static int
652 33 : load_value_partition(sql_trans *tr, sql_schema *syss, sql_part *pt)
653 : {
654 33 : sqlstore *store = tr->store;
655 33 : list *vals = NULL;
656 33 : oid rid;
657 33 : sql_table *values = find_sql_table(tr, syss, "value_partitions");
658 33 : assert(values);
659 :
660 33 : rids *rs = store->table_api.rids_select(tr, find_sql_column(values, "table_id"), &pt->member, &pt->member, NULL);
661 33 : if (rs == NULL)
662 : return -1;
663 :
664 33 : if (!rs)
665 : return -1;
666 33 : vals = list_create((fdestroy) &part_value_destroy);
667 33 : if (!vals) {
668 0 : store->table_api.rids_destroy(rs);
669 0 : return -1;
670 : }
671 :
672 140 : for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
673 107 : ptr cbat;
674 :
675 107 : const char *v = store->table_api.column_find_string_start(tr, find_sql_column(values, "value"), rid, &cbat);
676 107 : if (strNil(v)) { /* check for null value */
677 11 : pt->with_nills = true;
678 : } else {
679 96 : sql_part_value *nextv = ZNEW(sql_part_value);
680 96 : nextv->value =_STRDUP(v);
681 96 : nextv->length = strLen(v);
682 96 : list_append(vals, nextv);
683 : }
684 107 : store->table_api.column_find_string_end(cbat);
685 : }
686 33 : store->table_api.rids_destroy(rs);
687 33 : pt->part.values = vals;
688 33 : return 0;
689 : }
690 :
691 : static sql_part*
692 225 : load_part(sql_trans *tr, sql_table *mt, oid rid)
693 : {
694 225 : sql_part *pt = ZNEW(sql_part);
695 225 : sql_schema *syss = find_sql_schema(tr, "sys");
696 225 : sql_table *objects = find_sql_table(tr, syss, "objects");
697 225 : sqlid id;
698 225 : sqlstore *store = tr->store;
699 225 : const char *v;
700 225 : ptr cbat;
701 :
702 225 : assert(isMergeTable(mt) || isReplicaTable(mt));
703 225 : id = store->table_api.column_find_sqlid(tr, find_sql_column(objects, "id"), rid);
704 225 : if (is_int_nil(id)) { /* upgrade case, the id it's not initialized */
705 0 : id = store_next_oid(store);
706 0 : store->table_api.column_update_value(tr, find_sql_column(objects, "id"), rid, &id);
707 : }
708 225 : v = store->table_api.column_find_string_start(tr, find_sql_column(objects, "name"), rid, &cbat);
709 225 : base_init(NULL, &pt->base, id, 0, v);
710 225 : store->table_api.column_find_string_end(cbat);
711 225 : pt->t = mt;
712 225 : pt->member = store->table_api.column_find_sqlid(tr, find_sql_column(objects, "sub"), rid);
713 225 : list_append(mt->members, pt);
714 225 : return pt;
715 : }
716 :
717 : void
718 0 : sql_trans_update_tables(sql_trans* tr, sql_schema *s)
719 : {
720 0 : (void)tr;
721 0 : (void)s;
722 0 : }
723 :
724 : sql_base *
725 320401 : dup_base(sql_base *b)
726 : {
727 320401 : ATOMIC_INC(&b->refcnt);
728 320401 : return b;
729 : }
730 :
731 : static sql_table *
732 15985 : load_table(sql_trans *tr, sql_schema *s, res_table *rt_tables, res_table *rt_parts,
733 : res_table *rt_cols, res_table *rt_idx, res_table *rt_idxcols,
734 : res_table *rt_keys, res_table *rt_keycols,
735 : res_table *rt_triggers, res_table *rt_triggercols,
736 : sqlid tid)
737 : {
738 15985 : sqlstore *store = tr->store;
739 15985 : sql_table *t = ZNEW(sql_table);
740 15985 : sql_schema *syss = find_sql_schema(tr, "sys");
741 15985 : sql_table *tables = find_sql_table(tr, syss, "_tables");
742 15985 : sql_table *cols = find_sql_table(tr, syss, "_columns");
743 15985 : sql_table *idxs = find_sql_table(tr, syss, "idxs");
744 15985 : sql_table *keys = find_sql_table(tr, syss, "keys");
745 15985 : sql_table *triggers = find_sql_table(tr, syss, "triggers");
746 15985 : sqlid pcolid = int_nil;
747 15985 : str v, exp = NULL;
748 :
749 15985 : sqlid ntid = *(sqlid*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "id"));
750 15985 : assert(tid == ntid);
751 15985 : v = (char*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "name"));
752 15985 : base_init(NULL, &t->base, tid, 0, v);
753 15985 : t->query = NULL;
754 15985 : v = (char*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "query"));
755 31970 : if (!strNil(v))
756 12496 : t->query =_STRDUP(v);
757 15985 : t->type = *(sht*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "type"));
758 15985 : t->system = *(bit*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "system"));
759 15985 : t->commit_action = (ca_t)*(sht*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "commit_action"));
760 15985 : t->persistence = SQL_PERSIST;
761 15985 : if (t->commit_action)
762 0 : t->persistence = SQL_GLOBAL_TEMP;
763 15985 : if (isRemote(t))
764 34 : t->persistence = SQL_REMOTE;
765 15985 : t->access = *(sht*)store->table_api.table_fetch_value(rt_tables, find_sql_column(tables, "access"));
766 :
767 15985 : t->pkey = NULL;
768 15985 : t->s = s;
769 15985 : t->sz = COLSIZE;
770 :
771 15985 : t->columns = ol_new(NULL, (destroy_fptr) &column_destroy, store);
772 15985 : t->idxs = ol_new(NULL, (destroy_fptr) &idx_destroy, store);
773 15985 : t->keys = ol_new(NULL, (destroy_fptr) &key_destroy, store);
774 15985 : t->triggers = ol_new(NULL, (destroy_fptr) &trigger_destroy, store);
775 15985 : if (isMergeTable(t) || isReplicaTable(t))
776 105 : t->members = list_create((fdestroy) &part_destroy);
777 15985 : ATOMIC_PTR_INIT(&t->data, NULL);
778 :
779 15985 : if (isTable(t)) {
780 3384 : if (store->storage_api.create_del(tr, t) != LOG_OK) {
781 0 : TRC_ERROR(SQL_STORE, "Load table '%s' is missing 'deletes'", t->base.name);
782 0 : return NULL;
783 : }
784 : }
785 :
786 15985 : TRC_DEBUG(SQL_STORE, "Load table: %s\n", t->base.name);
787 :
788 15985 : sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
789 15985 : assert(partitions);
790 :
791 15985 : if (rt_parts->cur_row < rt_parts->nr_rows) {
792 1863 : ntid = *(sqlid*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "table_id"));
793 1863 : if (ntid == tid) {
794 51 : t->properties |= *(bte*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "type"));
795 :
796 51 : if (isPartitionedByColumnTable(t)) {
797 42 : pcolid = *(sqlid*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "column_id"));
798 : } else {
799 9 : v = (char*)store->table_api.table_fetch_value(rt_parts, find_sql_column(partitions, "expression"));
800 18 : assert(!strNil(v));
801 9 : exp =_STRDUP(v);
802 : }
803 51 : rt_parts->cur_row++;
804 : }
805 : }
806 :
807 15985 : assert((!isRangePartitionTable(t) && !isListPartitionTable(t)) || (!exp && !is_int_nil(pcolid)) || (exp && is_int_nil(pcolid)));
808 15985 : if (isPartitionedByExpressionTable(t)) {
809 9 : t->part.pexp = ZNEW(sql_expression);
810 9 : t->part.pexp->exp = exp;
811 9 : t->part.pexp->type = *sql_bind_localtype("void"); /* initialized at initialize_sql_parts */
812 9 : t->part.pexp->cols = list_create((fdestroy) &int_destroy);
813 : }
814 138730 : for ( ; rt_cols->cur_row < rt_cols->nr_rows; rt_cols->cur_row++) {
815 138603 : ntid = *(sqlid*)store->table_api.table_fetch_value(rt_cols, find_sql_column(cols, "table_id"));
816 157653 : while (instore(ntid)) {
817 19050 : rt_cols->cur_row++;
818 19050 : ntid = *(sqlid*)store->table_api.table_fetch_value(rt_cols, find_sql_column(cols, "table_id"));
819 : }
820 :
821 138603 : if (ntid != t->base.id)
822 : break;
823 122745 : sql_column* next = load_column(tr, t, rt_cols);
824 122745 : if (next == NULL) {
825 0 : table_destroy(store, t);
826 0 : return NULL;
827 : }
828 122745 : if (next->type.multiset)
829 0 : t->multiset=true;
830 122745 : if (next->type.type->composite)
831 0 : t->composite=true;
832 122745 : if (ol_add(t->columns, &next->base)) {
833 0 : table_destroy(store, t);
834 0 : return NULL;
835 : }
836 122745 : if (pcolid == next->base.id)
837 42 : t->part.pcol = next;
838 : }
839 :
840 15985 : if (!isKindOfTable(t))
841 : return t;
842 :
843 : /* load idx's first as the may be needed by the keys */
844 6017 : for ( ; rt_idx->cur_row < rt_idx->nr_rows; rt_idx->cur_row++) {
845 4946 : ntid = *(sqlid*)store->table_api.table_fetch_value(rt_idx, find_sql_column(idxs, "table_id"));
846 :
847 4946 : if (ntid != t->base.id)
848 : break;
849 2494 : sql_idx *i = load_idx(tr, t, rt_idx, rt_idxcols);
850 :
851 4988 : if (!i || ol_add(t->idxs, &i->base) ||
852 2494 : os_add(s->idxs, tr, i->base.name, dup_base(&i->base))) {
853 0 : table_destroy(store, t);
854 0 : return NULL;
855 : }
856 : }
857 :
858 5991 : for ( ; rt_keys->cur_row < rt_keys->nr_rows; rt_keys->cur_row++) {
859 4904 : ntid = *(sqlid*)store->table_api.table_fetch_value(rt_keys, find_sql_column(keys, "table_id"));
860 :
861 4904 : if (ntid != t->base.id)
862 : break;
863 2468 : sql_key *k = load_key(tr, t, rt_keys, rt_keycols);
864 :
865 4936 : if (!k || ol_add(t->keys, &k->base) ||
866 2468 : os_add(s->keys, tr, k->base.name, dup_base(&k->base)) ||
867 2468 : (isGlobal(t) && os_add(tr->cat->objects, tr, k->base.name, dup_base(&k->base)))) {
868 0 : table_destroy(store, t);
869 0 : return NULL;
870 : }
871 : }
872 :
873 : /* after loading keys and idxs, update properties derived from indexes that require keys */
874 3523 : if (ol_length(t->idxs))
875 4029 : for (node *n = ol_first_node(t->idxs); n; n = n->next)
876 2494 : create_sql_idx_done(tr, n->data);
877 :
878 3669 : for ( ; rt_triggers->cur_row < rt_triggers->nr_rows; rt_triggers->cur_row++) {
879 648 : ntid = *(sqlid*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(triggers, "table_id"));
880 :
881 648 : if (ntid < t->base.id && instore(ntid)) /* skip triggers on system tables ugh */
882 127 : continue;
883 521 : if (ntid != t->base.id)
884 : break;
885 19 : sql_trigger *k = load_trigger(tr, t, rt_triggers, rt_triggercols);
886 :
887 38 : if (!k || ol_add(t->triggers, &k->base) ||
888 19 : os_add(s->triggers, tr, k->base.name, dup_base(&k->base))) {
889 0 : table_destroy(store, t);
890 0 : return NULL;
891 : }
892 : }
893 : return t;
894 : }
895 :
896 : static sql_arg *
897 190887 : load_arg(sql_trans *tr, sql_schema *s, oid rid)
898 : {
899 190887 : sqlstore *store = tr->store;
900 190887 : sql_arg *a = ZNEW(sql_arg);
901 190887 : unsigned int digits, scale;
902 190887 : sql_schema *syss = find_sql_schema(tr, "sys");
903 190887 : sql_table *args = find_sql_table(tr, syss, "args");
904 190887 : const char *v, *tpe;
905 190887 : ptr cbat;
906 :
907 190887 : v = store->table_api.column_find_string_start(tr, find_sql_column(args, "name"), rid, &cbat);
908 190887 : a->name =_STRDUP(v);
909 190887 : store->table_api.column_find_string_end(cbat);
910 190887 : a->inout = store->table_api.column_find_bte(tr, find_sql_column(args, "inout"), rid);
911 190887 : digits = store->table_api.column_find_int(tr, find_sql_column(args, "type_digits"), rid);
912 190887 : scale = store->table_api.column_find_int(tr, find_sql_column(args, "type_scale"), rid);
913 :
914 190887 : tpe = store->table_api.column_find_string_start(tr, find_sql_column(args, "type"), rid, &cbat);
915 190887 : if (tpe && strcmp(tpe, "clob") == 0)
916 2566 : tpe = "varchar";
917 190887 : if (!sql_find_subtype(&a->type, tpe, digits, scale)) {
918 7689 : sql_type *lt = sql_trans_bind_type(tr, s, tpe);
919 7689 : if (lt == NULL) {
920 0 : TRC_ERROR(SQL_STORE, "SQL type '%s' is missing\n", tpe);
921 0 : store->table_api.column_find_string_end(cbat);
922 0 : return NULL;
923 : }
924 7689 : sql_init_subtype(&a->type, lt, digits, scale);
925 : }
926 190887 : a->type.multiset = store->table_api.column_find_bte(tr, find_sql_column(args, "multiset"), rid);
927 190887 : store->table_api.column_find_string_end(cbat);
928 190887 : return a;
929 : }
930 :
931 : static sql_type *
932 516 : load_type(sql_trans *tr, sql_schema *s, sqlid tid, subrids *rs)
933 : {
934 516 : sqlstore *store = tr->store;
935 516 : sql_type *t = ZNEW(sql_type);
936 516 : sql_schema *syss = find_sql_schema(tr, "sys");
937 516 : sql_table *types = find_sql_table(tr, syss, "types");
938 516 : oid rid;
939 516 : const char *v;
940 516 : ptr cbat;
941 :
942 516 : rid = store->table_api.column_find_row(tr, find_sql_column(types, "id"), &tid, NULL);
943 516 : v = store->table_api.column_find_string_start(tr, find_sql_column(types, "sqlname"), rid, &cbat);
944 516 : base_init(NULL, &t->base, tid, 0, v);
945 516 : store->table_api.column_find_string_end(cbat);
946 516 : v = store->table_api.column_find_string_start(tr, find_sql_column(types, "systemname"), rid, &cbat);
947 1032 : if (!strNil(v)) {
948 516 : assert(!rs);
949 516 : t->d.impl =_STRDUP(v);
950 516 : t->localtype = ATOMindex(t->d.impl);
951 : } else {
952 0 : assert(rs);
953 0 : t->composite = true;
954 0 : t->localtype = TYPE_int;
955 :
956 : /* load fields */
957 0 : t->d.fields = list_create((fdestroy) &arg_destroy);
958 0 : if (rs) {
959 0 : for (oid rid = store->table_api.subrids_next(rs); !is_oid_nil(rid); rid = store->table_api.subrids_next(rs)) {
960 0 : sql_arg *a = load_arg(tr, t->s, rid);
961 :
962 0 : if (a == NULL)
963 : return NULL;
964 0 : list_append(t->d.fields, a);
965 : }
966 : }
967 : }
968 516 : store->table_api.column_find_string_end(cbat);
969 516 : t->digits = store->table_api.column_find_int(tr, find_sql_column(types, "digits"), rid);
970 516 : t->scale = store->table_api.column_find_int(tr, find_sql_column(types, "scale"), rid);
971 516 : t->radix = store->table_api.column_find_int(tr, find_sql_column(types, "radix"), rid);
972 516 : t->eclass = (sql_class)store->table_api.column_find_int(tr, find_sql_column(types, "eclass"), rid);
973 516 : t->s = s;
974 516 : return t;
975 : }
976 :
977 : static sql_func *
978 66486 : load_func(sql_trans *tr, sql_schema *s, sqlid fid, subrids *rs)
979 : {
980 66486 : sqlstore *store = tr->store;
981 66486 : sql_func *t = ZNEW(sql_func);
982 66486 : sql_schema *syss = find_sql_schema(tr, "sys");
983 66486 : sql_table *funcs = find_sql_table(tr, syss, "functions");
984 66486 : oid rid;
985 66486 : bool update_env; /* hacky way to update env function */
986 66486 : const char *v;
987 66486 : ptr cbat;
988 :
989 66486 : rid = store->table_api.column_find_row(tr, find_sql_column(funcs, "id"), &fid, NULL);
990 66486 : v = store->table_api.column_find_string_start(tr, find_sql_column(funcs, "name"), rid, &cbat);
991 66486 : update_env = strcmp(v, "env") == 0;
992 66486 : base_init(NULL, &t->base, fid, 0, v);
993 66486 : store->table_api.column_find_string_end(cbat);
994 66486 : v = store->table_api.column_find_string_start(tr, find_sql_column(funcs, "func"), rid, &cbat);
995 66486 : update_env = update_env && strstr(v, "EXTERNAL NAME sql.sql_environment") != NULL;
996 66486 : if (update_env) {
997 : /* see creation of env in sql_create_env()
998 : * also see upgrade code in sql_upgrades.c */
999 : v = "CREATE FUNCTION env() RETURNS TABLE( name varchar(1024), value varchar(2048)) EXTERNAL NAME inspect.\"getEnvironment\";";
1000 : }
1001 66486 : t->imp =_STRDUP(v);
1002 66486 : store->table_api.column_find_string_end(cbat);
1003 66486 : if (update_env) {
1004 : v = "inspect";
1005 : } else {
1006 66486 : v = store->table_api.column_find_string_start(tr, find_sql_column(funcs, "mod"), rid, &cbat);
1007 : }
1008 66486 : if (strcmp(v, "pyapi") == 0 || /* pyapi module no longer used */
1009 66486 : strcmp(v, "pyapi3map") == 0) /* pyapi3map module no longer used */
1010 0 : t->mod =_STRDUP("pypapi3");
1011 : else
1012 66486 : t->mod =_STRDUP(v);
1013 66486 : if (!update_env)
1014 66486 : store->table_api.column_find_string_end(cbat);
1015 66486 : t->lang = (sql_flang) store->table_api.column_find_int(tr, find_sql_column(funcs, "language"), rid);
1016 66486 : t->instantiated = t->lang != FUNC_LANG_SQL && t->lang != FUNC_LANG_MAL;
1017 66486 : t->type = (sql_ftype) store->table_api.column_find_int(tr, find_sql_column(funcs, "type"), rid);
1018 66486 : t->side_effect = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "side_effect"), rid);
1019 66486 : t->varres = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "varres"), rid);
1020 66486 : t->vararg = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "vararg"), rid);
1021 66486 : t->system = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "system"), rid);
1022 66486 : t->semantics = (bool) store->table_api.column_find_bte(tr, find_sql_column(funcs, "semantics"), rid);
1023 66486 : bte order_spec = (bte) store->table_api.column_find_bte(tr, find_sql_column(funcs, "order_specification"), rid);
1024 66486 : t->res = NULL;
1025 66486 : t->s = s;
1026 66486 : t->fix_scale = SCALE_EQ;
1027 66486 : t->sa = NULL;
1028 66486 : if (t->lang != FUNC_LANG_INT) {
1029 66486 : t->query = t->imp;
1030 66486 : t->imp = NULL;
1031 : }
1032 : /* convert old PYTHON2 and PYTHON2_MAP to PYTHON and PYTHON_MAP
1033 : * see also function sql_update_jun2020() in sql_upgrades.c */
1034 66486 : if ((int) t->lang == 7 || (int) t->lang == 8) /* MAP_PY old FUNC_LANG_PY2 */
1035 0 : t->lang = FUNC_LANG_PY;
1036 66486 : else if ((int) t->lang == 9 || (int) t->lang == 11) /* old FUNC_LANG_MAP_PY2 or MAP_PY3 */
1037 0 : t->lang = FUNC_LANG_PY;
1038 66486 : if (LANG_EXT(t->lang)) { /* instantiate functions other than sql and mal */
1039 76 : switch(t->type) {
1040 10 : case F_AGGR:
1041 10 : t->imp =_STRDUP("eval_aggr");
1042 10 : break;
1043 0 : case F_LOADER:
1044 0 : t->imp =_STRDUP("eval_loader");
1045 0 : break;
1046 66 : default: /* for every other function type at the moment */
1047 66 : t->imp =_STRDUP("eval");
1048 : }
1049 : }
1050 66486 : if (order_spec == 2)
1051 6468 : t->order_required = true;
1052 66486 : if (order_spec == 1)
1053 254 : t->opt_order = true;
1054 :
1055 66486 : TRC_DEBUG(SQL_STORE, "Load function: %s\n", t->base.name);
1056 :
1057 66486 : t->ops = list_create((fdestroy) &arg_destroy);
1058 66486 : if (rs) {
1059 255593 : for (rid = store->table_api.subrids_next(rs); !is_oid_nil(rid); rid = store->table_api.subrids_next(rs)) {
1060 190887 : sql_arg *a = load_arg(tr, t->s, rid);
1061 :
1062 190887 : if (a == NULL)
1063 : return NULL;
1064 190887 : if (a->inout == ARG_OUT) {
1065 87379 : if (!t->res)
1066 56044 : t->res = list_create((fdestroy) &arg_destroy);
1067 87379 : list_append(t->res, a);
1068 : } else {
1069 103508 : list_append(t->ops, a);
1070 : }
1071 : }
1072 : }
1073 66486 : if (t->type == F_FILT && (list_length(t->ops) == 2 || list_length(t->ops) == 3))
1074 1718 : if (!find_keyword(t->base.name))
1075 1337 : (void) keywords_insert(t->base.name, KW_OPERATORS);
1076 : return t;
1077 : }
1078 :
1079 : static sql_sequence *
1080 36 : load_seq(sql_trans *tr, sql_schema * s, oid rid)
1081 : {
1082 36 : sqlstore *store = tr->store;
1083 36 : sql_sequence *seq = ZNEW(sql_sequence);
1084 36 : sql_schema *syss = find_sql_schema(tr, "sys");
1085 36 : sql_table *seqs = find_sql_table(tr, syss, "sequences");
1086 36 : sqlid sid;
1087 36 : const char *v;
1088 36 : ptr cbat;
1089 :
1090 36 : sid = store->table_api.column_find_sqlid(tr, find_sql_column(seqs, "id"), rid);
1091 36 : v = store->table_api.column_find_string_start(tr, find_sql_column(seqs, "name"), rid, &cbat);
1092 36 : base_init(NULL, &seq->base, sid, 0, v);
1093 36 : store->table_api.column_find_string_end(cbat);
1094 36 : seq->start = store->table_api.column_find_lng(tr, find_sql_column(seqs, "start"), rid);
1095 36 : seq->minvalue = store->table_api.column_find_lng(tr, find_sql_column(seqs, "minvalue"), rid);
1096 36 : seq->maxvalue = store->table_api.column_find_lng(tr, find_sql_column(seqs, "maxvalue"), rid);
1097 36 : seq->increment = store->table_api.column_find_lng(tr, find_sql_column(seqs, "increment"), rid);
1098 36 : seq->cacheinc = store->table_api.column_find_lng(tr, find_sql_column(seqs, "cacheinc"), rid);
1099 36 : seq->cycle = (bit) store->table_api.column_find_bte(tr, find_sql_column(seqs, "cycle"), rid);
1100 36 : seq->s = s;
1101 36 : return seq;
1102 : }
1103 :
1104 : static void
1105 1380 : sql_trans_update_schema(sql_trans *tr, oid rid)
1106 : {
1107 1380 : sqlstore *store = tr->store;
1108 1380 : sql_schema *s = NULL, *syss = find_sql_schema(tr, "sys");
1109 1380 : sql_table *ss = find_sql_table(tr, syss, "schemas");
1110 1380 : sqlid sid;
1111 1380 : str v;
1112 :
1113 1380 : sid = store->table_api.column_find_sqlid(tr, find_sql_column(ss, "id"), rid);
1114 1380 : s = find_sql_schema_id(tr, sid);
1115 :
1116 1380 : if (s==NULL)
1117 : return ;
1118 :
1119 1380 : TRC_DEBUG(SQL_STORE, "Update schema: %s %d\n", s->base.name, s->base.id);
1120 :
1121 1380 : v = store->table_api.column_find_value(tr, find_sql_column(ss, "name"), rid);
1122 1380 : if (!v)
1123 : return; /* TODO do better than this */
1124 1380 : _DELETE(s->base.name);
1125 1380 : base_init(NULL, &s->base, sid, 0, v);
1126 1380 : _DELETE(v);
1127 1380 : s->auth_id = store->table_api.column_find_sqlid(tr, find_sql_column(ss, "authorization"), rid);
1128 1380 : s->system = (bit) store->table_api.column_find_bte(tr, find_sql_column(ss, "system"), rid);
1129 1380 : s->owner = store->table_api.column_find_sqlid(tr, find_sql_column(ss, "owner"), rid);
1130 : }
1131 :
1132 : static sql_schema *
1133 795 : load_schema(sql_trans *tr, res_table *rt_schemas, res_table *rt_tables, res_table *rt_parts,
1134 : res_table *rt_cols, res_table *rt_idx, res_table *rt_idxcols,
1135 : res_table *rt_keys, res_table *rt_keycols,
1136 : res_table *rt_triggers, res_table *rt_triggercols)
1137 : {
1138 795 : sqlstore *store = tr->store;
1139 795 : sql_schema *s = NULL, *syss = find_sql_schema(tr, "sys");
1140 795 : sql_table *ss = find_sql_table(tr, syss, "schemas");
1141 795 : sql_table *types = find_sql_table(tr, syss, "types");
1142 795 : sql_table *tables = find_sql_table(tr, syss, "_tables");
1143 795 : sql_table *funcs = find_sql_table(tr, syss, "functions");
1144 795 : sql_table *seqs = find_sql_table(tr, syss, "sequences");
1145 795 : sql_column *type_schema, *type_id, *table_schema, *table_id;
1146 795 : sql_column *func_schema, *func_id, *seq_schema, *seq_id;
1147 795 : rids *rs;
1148 :
1149 795 : sqlid sid = *(sqlid*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "id"));
1150 795 : if (instore(sid)) {
1151 254 : s = find_sql_schema_id(tr, sid);
1152 :
1153 254 : if (s==NULL) {
1154 0 : char *name = (char*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "name"));
1155 0 : s = find_sql_schema(tr, name);
1156 0 : if (s == NULL) {
1157 0 : GDKerror("SQL schema missing or incompatible, rebuild from archive");
1158 0 : return NULL;
1159 : }
1160 : }
1161 254 : s->base.id = sid;
1162 : } else {
1163 541 : s = ZNEW(sql_schema);
1164 541 : if (s == NULL)
1165 : return NULL;
1166 541 : char *name = (char*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "name"));
1167 541 : base_init(NULL, &s->base, sid, 0, name);
1168 541 : s->auth_id = *(sqlid*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "authorization"));
1169 541 : s->system = *(bte*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "system"));
1170 541 : s->owner = *(sqlid*)store->table_api.table_fetch_value(rt_schemas, find_sql_column(ss, "owner"));
1171 :
1172 541 : s->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
1173 541 : s->types = os_new(NULL, (destroy_fptr) &type_destroy, false, true, true, false, store);
1174 541 : s->funcs = os_new(NULL, (destroy_fptr) &func_destroy, false, false, false, false, store);
1175 541 : s->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
1176 541 : s->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
1177 541 : s->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
1178 541 : s->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
1179 541 : s->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
1180 : }
1181 :
1182 795 : TRC_DEBUG(SQL_STORE, "Load schema: %s %d\n", s->base.name, s->base.id);
1183 :
1184 795 : sqlid tmpid = FUNC_OIDS;
1185 :
1186 : /* first load simple types */
1187 795 : type_schema = find_sql_column(types, "schema_id");
1188 795 : type_id = find_sql_column(types, "id");
1189 795 : rs = store->table_api.rids_select(tr, type_schema, &s->base.id, &s->base.id, type_id, &tmpid, NULL, NULL);
1190 795 : if (rs == NULL) {
1191 0 : schema_destroy(store, s);
1192 0 : return NULL;
1193 : }
1194 795 : if (!store->table_api.rids_empty(rs)) {
1195 127 : sql_table *args = find_sql_table(tr, syss, "args");
1196 127 : sql_column *arg_type_id = find_sql_column(args, "func_id");
1197 127 : sql_column *arg_number = find_sql_column(args, "number");
1198 127 : subrids *nrs = store->table_api.subrids_create(tr, rs, type_id, arg_type_id, arg_number);
1199 127 : if (!nrs) {
1200 0 : store->table_api.rids_destroy(rs);
1201 0 : schema_destroy(store, s);
1202 0 : return NULL;
1203 : }
1204 :
1205 127 : sqlid tid;
1206 127 : sql_type *t;
1207 :
1208 : /* Handle all simple types (no args aka fields) */
1209 127 : rs = store->table_api.rids_diff(tr, rs, type_id, nrs, arg_type_id);
1210 127 : if (!rs) {
1211 0 : store->table_api.subrids_destroy(nrs);
1212 0 : schema_destroy(store, s);
1213 0 : return NULL;
1214 : }
1215 643 : for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
1216 516 : tid = store->table_api.column_find_sqlid(tr, type_id, rid);
1217 516 : t = load_type(tr, s, tid, NULL);
1218 516 : if (t == NULL) {
1219 0 : store->table_api.subrids_destroy(nrs);
1220 0 : store->table_api.rids_destroy(rs);
1221 0 : schema_destroy(store, s);
1222 0 : return NULL;
1223 : }
1224 516 : if (os_add(s->types, tr, t->base.name, &t->base)) {
1225 0 : store->table_api.subrids_destroy(nrs);
1226 0 : store->table_api.rids_destroy(rs);
1227 0 : schema_destroy(store, s);
1228 0 : return NULL;
1229 : }
1230 : }
1231 :
1232 : /* Handle all composite types (no args aka fields) */
1233 127 : for (tid = store->table_api.subrids_nextid(nrs); tid >= 0; tid = store->table_api.subrids_nextid(nrs)) {
1234 0 : t = load_type(tr, s, tid, nrs);
1235 0 : if (t == NULL) {
1236 0 : store->table_api.subrids_destroy(nrs);
1237 0 : store->table_api.rids_destroy(rs);
1238 0 : schema_destroy(store, s);
1239 0 : return NULL;
1240 : }
1241 0 : if (os_add(s->types, tr, t->base.name, &t->base)) {
1242 0 : schema_destroy(store, s);
1243 0 : return NULL;
1244 : }
1245 : }
1246 127 : store->table_api.subrids_destroy(nrs);
1247 : }
1248 795 : store->table_api.rids_destroy(rs);
1249 :
1250 : /* second tables */
1251 795 : table_schema = find_sql_column(tables, "schema_id");
1252 795 : table_id = find_sql_column(tables, "id");
1253 20242 : for ( ; rt_tables->cur_row < rt_tables->nr_rows; rt_tables->cur_row++) {
1254 19316 : sqlid nsid = *(sqlid*)store->table_api.table_fetch_value(rt_tables, table_schema);
1255 19316 : sqlid tid = *(sqlid*)store->table_api.table_fetch_value(rt_tables, table_id);
1256 19316 : if (nsid > s->base.id)
1257 : break;
1258 18652 : if (nsid < s->base.id)
1259 0 : assert(0);
1260 34637 : if (!instore(tid)) {
1261 15985 : sql_table *t = load_table(tr, s, rt_tables, rt_parts,
1262 : rt_cols, rt_idx, rt_idxcols, rt_keys, rt_keycols, rt_triggers, rt_triggercols, tid);
1263 15985 : if (t == NULL && store->debug&8) /* try to continue without this table */
1264 0 : continue;
1265 0 : if (t == NULL) {
1266 0 : schema_destroy(store, s);
1267 0 : return NULL;
1268 : }
1269 15985 : if (os_add(s->tables, tr, t->base.name, &t->base)) {
1270 0 : schema_destroy(store, s);
1271 0 : return NULL;
1272 : }
1273 : }
1274 : }
1275 :
1276 : /* next functions which could use these types */
1277 795 : func_schema = find_sql_column(funcs, "schema_id");
1278 795 : func_id = find_sql_column(funcs, "id");
1279 795 : rs = store->table_api.rids_select(tr, func_schema, &s->base.id, &s->base.id, func_id, &tmpid, NULL, NULL);
1280 795 : if (rs == NULL) {
1281 0 : schema_destroy(store, s);
1282 0 : return NULL;
1283 : }
1284 795 : if (!store->table_api.rids_empty(rs)) {
1285 527 : sql_table *args = find_sql_table(tr, syss, "args");
1286 527 : sql_column *arg_func_id = find_sql_column(args, "func_id");
1287 527 : sql_column *arg_number = find_sql_column(args, "number");
1288 527 : subrids *nrs = store->table_api.subrids_create(tr, rs, func_id, arg_func_id, arg_number);
1289 527 : if (!nrs) {
1290 0 : store->table_api.rids_destroy(rs);
1291 0 : schema_destroy(store, s);
1292 0 : return NULL;
1293 : }
1294 527 : sqlid fid;
1295 527 : sql_func *f;
1296 :
1297 65233 : for (fid = store->table_api.subrids_nextid(nrs); fid >= 0; fid = store->table_api.subrids_nextid(nrs)) {
1298 64706 : f = load_func(tr, s, fid, nrs);
1299 64706 : if (f == NULL) {
1300 0 : store->table_api.subrids_destroy(nrs);
1301 0 : store->table_api.rids_destroy(rs);
1302 0 : schema_destroy(store, s);
1303 0 : return NULL;
1304 : }
1305 64706 : if (os_add(s->funcs, tr, f->base.name, &f->base)) {
1306 0 : schema_destroy(store, s);
1307 0 : return NULL;
1308 : }
1309 : }
1310 : /* Handle all procedures without arguments (no args) */
1311 527 : rs = store->table_api.rids_diff(tr, rs, func_id, nrs, arg_func_id);
1312 527 : if (!rs) {
1313 0 : store->table_api.subrids_destroy(nrs);
1314 0 : schema_destroy(store, s);
1315 0 : return NULL;
1316 : }
1317 2307 : for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
1318 1780 : fid = store->table_api.column_find_sqlid(tr, func_id, rid);
1319 1780 : f = load_func(tr, s, fid, NULL);
1320 1780 : if (f == NULL) {
1321 0 : store->table_api.subrids_destroy(nrs);
1322 0 : store->table_api.rids_destroy(rs);
1323 0 : schema_destroy(store, s);
1324 0 : return NULL;
1325 : }
1326 1780 : if (os_add(s->funcs, tr, f->base.name, &f->base)) {
1327 0 : store->table_api.subrids_destroy(nrs);
1328 0 : store->table_api.rids_destroy(rs);
1329 0 : schema_destroy(store, s);
1330 0 : return NULL;
1331 : }
1332 : }
1333 527 : store->table_api.subrids_destroy(nrs);
1334 : }
1335 795 : store->table_api.rids_destroy(rs);
1336 :
1337 : /* last sequence numbers */
1338 795 : seq_schema = find_sql_column(seqs, "schema_id");
1339 795 : seq_id = find_sql_column(seqs, "id");
1340 795 : rs = store->table_api.rids_select(tr, seq_schema, &s->base.id, &s->base.id, seq_id, &tmpid, NULL, NULL);
1341 795 : if (rs == NULL) {
1342 0 : schema_destroy(store, s);
1343 0 : return NULL;
1344 : }
1345 831 : for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
1346 36 : sql_sequence *seq = load_seq(tr, s, rid);
1347 36 : if (os_add(s->seqs, tr, seq->base.name, &seq->base)) {
1348 0 : schema_destroy(store, s);
1349 0 : store->table_api.rids_destroy(rs);
1350 0 : return NULL;
1351 : }
1352 : }
1353 795 : store->table_api.rids_destroy(rs);
1354 :
1355 795 : struct os_iter oi;
1356 795 : os_iterator(&oi, s->tables, tr, NULL);
1357 19447 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
1358 18652 : sql_table *t = (sql_table*)b;
1359 18652 : if (isMergeTable(t) || isReplicaTable(t)) {
1360 105 : sql_table *objects = find_sql_table(tr, syss, "objects");
1361 105 : sql_column *mt_nr = find_sql_column(objects, "nr");
1362 105 : sql_column *mt_sub = find_sql_column(objects, "sub");
1363 105 : rids *rs = store->table_api.rids_select(tr, mt_nr, &t->base.id, &t->base.id, NULL);
1364 105 : if (rs == NULL) {
1365 0 : schema_destroy(store, s);
1366 0 : return NULL;
1367 : }
1368 105 : rs = store->table_api.rids_orderby(tr, rs, mt_sub);
1369 105 : if (rs == NULL) {
1370 0 : schema_destroy(store, s);
1371 0 : return NULL;
1372 : }
1373 330 : for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
1374 225 : sql_part *pt = load_part(tr, t, rid);
1375 225 : if (isRangePartitionTable(t)) {
1376 78 : if (load_range_partition(tr, syss, pt) < 0) {
1377 0 : schema_destroy(store, s);
1378 0 : return NULL;
1379 : }
1380 147 : } else if (isListPartitionTable(t)) {
1381 33 : load_value_partition(tr, syss, pt);
1382 : }
1383 225 : if (os_add(s->parts, tr, pt->base.name, dup_base(&pt->base))) {
1384 0 : schema_destroy(store, s);
1385 0 : store->table_api.rids_destroy(rs);
1386 0 : return NULL;
1387 : }
1388 : }
1389 105 : store->table_api.rids_destroy(rs);
1390 : }
1391 : }
1392 : return s;
1393 : }
1394 :
1395 : int
1396 230 : sql_trans_update_schemas(sql_trans* tr)
1397 : {
1398 230 : sqlstore *store = tr->store;
1399 230 : sql_schema *syss = find_sql_schema(tr, "sys");
1400 230 : sql_table *sysschema = find_sql_table(tr, syss, "schemas");
1401 230 : sql_column *sysschema_ids = find_sql_column(sysschema, "id");
1402 230 : rids *schemas = store->table_api.rids_select(tr, sysschema_ids, NULL, NULL);
1403 230 : oid rid;
1404 :
1405 230 : if (schemas == NULL)
1406 : return -1;
1407 230 : TRC_DEBUG(SQL_STORE, "Update schemas\n");
1408 :
1409 1610 : for (rid = store->table_api.rids_next(schemas); !is_oid_nil(rid); rid = store->table_api.rids_next(schemas)) {
1410 1380 : sql_trans_update_schema(tr, rid);
1411 : }
1412 230 : store->table_api.rids_destroy(schemas);
1413 230 : return 0;
1414 : }
1415 :
1416 : static bool
1417 127 : load_trans(sql_trans* tr)
1418 : {
1419 127 : sqlstore *store = tr->store;
1420 127 : sql_schema *syss = find_sql_schema(tr, "sys");
1421 127 : sql_table *sysschema = find_sql_table(tr, syss, "schemas");
1422 127 : sql_table *systables = find_sql_table(tr, syss, "_tables");
1423 127 : sql_table *sysparts = find_sql_table(tr, syss, "table_partitions");
1424 127 : sql_table *syscols = find_sql_table(tr, syss, "_columns");
1425 127 : sql_table *sysidx = find_sql_table(tr, syss, "idxs");
1426 127 : sql_table *syskeys = find_sql_table(tr, syss, "keys");
1427 127 : sql_table *systriggers = find_sql_table(tr, syss, "triggers");
1428 127 : sql_table *sysobjects = find_sql_table(tr, syss, "objects");
1429 127 : sql_column *sysschema_ids = find_sql_column(sysschema, "id");
1430 127 : bool ok = true;
1431 :
1432 127 : TRC_DEBUG(SQL_STORE, "Load transaction\n");
1433 127 : assert(sysschema);
1434 127 : assert(systables);
1435 127 : assert(sysparts);
1436 127 : assert(syscols);
1437 127 : assert(sysidx);
1438 127 : assert(syskeys);
1439 127 : assert(systriggers);
1440 127 : assert(sysobjects);
1441 127 : assert(sysschema_ids);
1442 :
1443 127 : res_table *rt_schemas = store->table_api.table_orderby(tr, sysschema, NULL, NULL, NULL, NULL, sysschema_ids, NULL);
1444 127 : res_table *rt_tables = store->table_api.table_orderby(tr, systables, NULL, NULL, NULL, NULL,
1445 : find_sql_column(systables, "schema_id"),
1446 : find_sql_column(systables, "id"), NULL);
1447 127 : res_table *rt_parts = store->table_api.table_orderby(tr, sysparts,
1448 : find_sql_column(sysparts, "table_id"),
1449 : find_sql_column(systables, "id"),
1450 : NULL, NULL,
1451 : find_sql_column(systables, "schema_id"), /* order also on schema_id */
1452 : find_sql_column(sysparts, "table_id"), NULL);
1453 127 : res_table *rt_cols = store->table_api.table_orderby(tr, syscols,
1454 : find_sql_column(syscols, "table_id"),
1455 : find_sql_column(systables, "id"),
1456 : NULL, NULL,
1457 : find_sql_column(systables, "schema_id"), /* order also on schema_id */
1458 : find_sql_column(syscols, "table_id"),
1459 : find_sql_column(syscols, "number"), NULL);
1460 :
1461 127 : res_table *rt_idx = store->table_api.table_orderby(tr, sysidx,
1462 : find_sql_column(sysidx, "table_id"),
1463 : find_sql_column(systables, "id"),
1464 : NULL, NULL,
1465 : find_sql_column(systables, "schema_id"), /* order also on schema_id */
1466 : find_sql_column(sysidx, "table_id"),
1467 : find_sql_column(sysidx, "id"), NULL);
1468 127 : res_table *rt_idxcols = store->table_api.table_orderby(tr, sysobjects,
1469 : find_sql_column(sysobjects, "id"),
1470 : find_sql_column(sysidx, "id"),
1471 : find_sql_column(sysidx, "table_id"),
1472 : find_sql_column(systables, "id"),
1473 : find_sql_column(systables, "schema_id"), /* order also on schema_id, table_id */
1474 : find_sql_column(sysidx, "table_id"),
1475 : find_sql_column(sysobjects, "id"),
1476 : find_sql_column(sysobjects, "nr"), NULL);
1477 127 : res_table *rt_keys = store->table_api.table_orderby(tr, syskeys,
1478 : find_sql_column(syskeys, "table_id"),
1479 : find_sql_column(systables, "id"),
1480 : NULL, NULL,
1481 : find_sql_column(systables, "schema_id"), /* order also on schema_id */
1482 : find_sql_column(syskeys, "table_id"),
1483 : find_sql_column(syskeys, "id"), NULL);
1484 127 : res_table *rt_keycols = store->table_api.table_orderby(tr, sysobjects,
1485 : find_sql_column(sysobjects, "id"),
1486 : find_sql_column(syskeys, "id"),
1487 : find_sql_column(syskeys, "table_id"),
1488 : find_sql_column(systables, "id"),
1489 : find_sql_column(systables, "schema_id"), /* order also on schema_id, table_id */
1490 : find_sql_column(syskeys, "table_id"),
1491 : find_sql_column(sysobjects, "id"),
1492 : find_sql_column(sysobjects, "nr"), NULL);
1493 127 : res_table *rt_tabletriggers = store->table_api.table_orderby(tr, systriggers,
1494 : find_sql_column(systriggers, "table_id"),
1495 : find_sql_column(systables, "id"),
1496 : NULL, NULL,
1497 : find_sql_column(systables, "schema_id"), /* order also on schema_id */
1498 : find_sql_column(systriggers, "table_id"),
1499 : find_sql_column(systriggers, "id"), NULL);
1500 127 : res_table *rt_triggercols = store->table_api.table_orderby(tr, sysobjects,
1501 : find_sql_column(sysobjects, "id"),
1502 : find_sql_column(systriggers, "id"),
1503 : find_sql_column(systriggers, "table_id"),
1504 : find_sql_column(systables, "id"),
1505 : find_sql_column(systables, "schema_id"), /* order also on schema_id, table_id */
1506 : find_sql_column(systriggers, "table_id"),
1507 : find_sql_column(sysobjects, "id"),
1508 : find_sql_column(sysobjects, "nr"), NULL);
1509 127 : res_table *rt_triggers = store->table_api.table_orderby(tr, systriggers,
1510 : NULL, NULL, NULL, NULL,
1511 : find_sql_column(systriggers, "id"),
1512 : find_sql_column(systriggers, "table_id"), NULL);
1513 1049 : for ( ; rt_schemas->cur_row < rt_schemas->nr_rows; rt_schemas->cur_row++) {
1514 795 : sql_schema *ns = load_schema(tr, rt_schemas, rt_tables, rt_parts,
1515 : rt_cols, rt_idx, rt_idxcols, rt_keys, rt_keycols, rt_tabletriggers, rt_triggercols);
1516 795 : if (ns == NULL) {
1517 0 : ok = false;
1518 0 : goto finish;
1519 : }
1520 1336 : if (!instore(ns->base.id)) {
1521 541 : if (os_add(tr->cat->schemas, tr, ns->base.name, &ns->base)) {
1522 0 : ok = false;
1523 0 : goto finish;
1524 : }
1525 541 : if (isTempSchema(ns))
1526 0 : tr->tmp = ns;
1527 : }
1528 : }
1529 127 : if (rt_triggers) {
1530 273 : for ( ; rt_triggers->cur_row < rt_triggers->nr_rows; rt_triggers->cur_row++) {
1531 146 : sqlid ntid = *(sqlid*)store->table_api.table_fetch_value(rt_triggers, find_sql_column(systriggers, "table_id"));
1532 146 : if (ntid != int_nil)
1533 146 : continue;
1534 0 : sql_trigger *k = load_trigger(tr, NULL, rt_triggers, NULL);
1535 :
1536 0 : if (!k || os_add(syss->triggers, tr, k->base.name, &k->base)) {
1537 0 : ok = false;
1538 0 : goto finish;
1539 : }
1540 : }
1541 : }
1542 :
1543 127 : finish:
1544 127 : store->table_api.table_result_destroy(rt_schemas);
1545 127 : store->table_api.table_result_destroy(rt_tables);
1546 127 : store->table_api.table_result_destroy(rt_parts);
1547 127 : store->table_api.table_result_destroy(rt_cols);
1548 127 : store->table_api.table_result_destroy(rt_idx);
1549 127 : store->table_api.table_result_destroy(rt_idxcols);
1550 127 : store->table_api.table_result_destroy(rt_keys);
1551 127 : store->table_api.table_result_destroy(rt_keycols);
1552 127 : store->table_api.table_result_destroy(rt_tabletriggers);
1553 127 : store->table_api.table_result_destroy(rt_triggercols);
1554 127 : store->table_api.table_result_destroy(rt_triggers);
1555 127 : return ok;
1556 : }
1557 :
1558 : static sqlid
1559 1439465 : next_oid(sqlstore *store)
1560 : {
1561 1439465 : sqlid id = 0;
1562 1439465 : id = (sqlid) ATOMIC_ADD(&store->obj_id, 1);
1563 1439465 : assert(id < 2000000000);
1564 1439465 : return id;
1565 : }
1566 :
1567 : sqlid
1568 31175 : store_next_oid(sqlstore *store)
1569 : {
1570 31175 : return next_oid(store);
1571 : }
1572 :
1573 : static int
1574 230 : insert_schemas(sql_trans *tr)
1575 : {
1576 230 : int res = LOG_OK;
1577 230 : sqlstore *store = tr->store;
1578 230 : sql_schema *syss = find_sql_schema(tr, "sys");
1579 230 : sql_table *sysschema = find_sql_table(tr, syss, "schemas");
1580 230 : sql_table *systable = find_sql_table(tr, syss, "_tables");
1581 230 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
1582 230 : node *o;
1583 :
1584 230 : struct os_iter si;
1585 230 : os_iterator(&si, tr->cat->schemas, tr, NULL);
1586 920 : for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
1587 690 : sql_schema *s = (sql_schema*)b;
1588 690 : char *strnil = (char*)ATOMnilptr(TYPE_str);
1589 :
1590 690 : if (isDeclaredSchema(s))
1591 230 : continue;
1592 460 : if ((res = store->table_api.table_insert(tr, sysschema, &s->base.id, &s->base.name, &s->auth_id, &s->owner, &s->system)))
1593 0 : return res;
1594 460 : struct os_iter oi;
1595 460 : os_iterator(&oi, s->tables, tr, NULL);
1596 5290 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
1597 4830 : sql_table *t = (sql_table*)b;
1598 4830 : sht ca = t->commit_action;
1599 :
1600 4830 : if ((res = store->table_api.table_insert(tr, systable, &t->base.id, &t->base.name, &s->base.id, &strnil, &t->type, &t->system, &ca, &t->access)))
1601 0 : return res;
1602 39330 : for (o = t->columns->l->h; o; o = o->next) {
1603 34500 : sql_column *c = o->data;
1604 :
1605 34500 : if ((res = store->table_api.table_insert(tr, syscolumn, &c->base.id, &c->base.name, &c->type.type->base.name, &c->type.digits, &c->type.scale,
1606 34500 : &t->base.id, (c->def) ? &c->def : &strnil, &c->null, &c->colnr, (c->storage_type)? &c->storage_type : &strnil, &c->column_type, &c->type.multiset)))
1607 0 : return res;
1608 : }
1609 : }
1610 : }
1611 : return res;
1612 : }
1613 :
1614 : static int
1615 230 : insert_types(sql_trans *tr, sql_table *systype)
1616 : {
1617 230 : int res = LOG_OK;
1618 230 : sqlstore *store = tr->store;
1619 7126 : for (node *n = types->h; n; n = n->next) {
1620 6896 : sql_type *t = n->data;
1621 6896 : int radix = t->radix, eclass = (int) t->eclass;
1622 6896 : sqlid next_schema = t->s ? t->s->base.id : 0;
1623 :
1624 6896 : char *strnil = (char*)ATOMnilptr(TYPE_str);
1625 6896 : if ((res = store->table_api.table_insert(tr, systype, &t->base.id, t->d.impl ? &t->d.impl : &strnil, &t->base.name, &t->digits, &t->scale, &radix, &eclass, &next_schema)))
1626 0 : return res;
1627 : }
1628 : return res;
1629 : }
1630 :
1631 : static int
1632 329240 : insert_args(sql_trans *tr, sql_table *sysarg, list *args, sqlid funcid, const char *arg_def, int *number)
1633 : {
1634 329240 : int res = LOG_OK;
1635 329240 : sqlstore *store = tr->store;
1636 768820 : for (node *n = args->h; n; n = n->next) {
1637 439580 : sql_arg *a = n->data;
1638 439580 : sqlid id = next_oid(tr->store);
1639 439580 : int next_number = (*number)++;
1640 439580 : char buf[32], *next_name;
1641 :
1642 439580 : if (a->name) {
1643 0 : next_name = a->name;
1644 : } else {
1645 439580 : snprintf(buf, sizeof(buf), arg_def, next_number);
1646 439580 : next_name = buf;
1647 : }
1648 439580 : if ((res = store->table_api.table_insert(tr, sysarg, &id, &funcid, &next_name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &next_number, &a->type.multiset)))
1649 0 : return res;
1650 : }
1651 : return res;
1652 : }
1653 :
1654 : static int
1655 230 : insert_functions(sql_trans *tr, sql_table *sysfunc, list *funcs_list, sql_table *sysarg)
1656 : {
1657 230 : int res = LOG_OK;
1658 230 : sqlstore *store = tr->store;
1659 218900 : for (node *n = funcs_list->h; n; n = n->next) {
1660 218670 : sql_func *f = n->data;
1661 218670 : int number = 0, ftype = (int) f->type, flang = (int) FUNC_LANG_INT;
1662 218670 : sqlid next_schema = f->s ? f->s->base.id : 0;
1663 218670 : bit se = f->side_effect, vares = f->varres, varg = f->vararg, system = f->system, sem = f->semantics;
1664 218670 : bte order = f->order_required?2:f->opt_order?1:0;
1665 :
1666 218670 : if (f->private) /* don't serialize private functions because they cannot be seen by users */
1667 53820 : continue;
1668 164850 : if ((res = store->table_api.table_insert(tr, sysfunc, &f->base.id, &f->base.name, &f->imp, &f->mod, &flang, &ftype, &se, &vares, &varg, &next_schema, &system, &sem, &order)))
1669 0 : return res;
1670 164850 : if (f->res && (res = insert_args(tr, sysarg, f->res, f->base.id, "res_%d", &number)))
1671 0 : return res;
1672 164850 : if (f->ops && (res = insert_args(tr, sysarg, f->ops, f->base.id, "arg_%d", &number)))
1673 0 : return res;
1674 : }
1675 : return res;
1676 : }
1677 :
1678 : static int
1679 589257 : table_next_column_nr(sql_table *t)
1680 : {
1681 589257 : int nr = ol_length(t->columns);
1682 589257 : if (nr) {
1683 513119 : node *n = ol_last_node(t->columns);
1684 513119 : if (n) {
1685 513119 : sql_column *c = n->data;
1686 :
1687 513119 : nr = c->colnr+1;
1688 : }
1689 : }
1690 589257 : return nr;
1691 : }
1692 :
1693 : static sql_column *
1694 53550 : bootstrap_create_column(sql_trans *tr, sql_table *t, const char *name, sqlid id, const char *sqltype, unsigned int digits)
1695 : {
1696 53550 : sqlstore *store = tr->store;
1697 53550 : sql_column *col = ZNEW(sql_column);
1698 :
1699 53550 : if ((sqlid) ATOMIC_GET(&store->obj_id) <= id)
1700 9639 : ATOMIC_SET(&store->obj_id, id + 1);
1701 53550 : TRC_DEBUG(SQL_STORE, "Create column: %s\n", name);
1702 :
1703 53550 : base_init(NULL, &col->base, id, t->base.new, name);
1704 53550 : assert(col->base.id > 0);
1705 53550 : sql_find_subtype(&col->type, sqltype, digits, 0);
1706 53550 : col->def = NULL;
1707 53550 : col->null = 1;
1708 53550 : col->colnr = table_next_column_nr(t);
1709 53550 : col->t = t;
1710 53550 : col->unique = 0;
1711 53550 : col->storage_type = NULL;
1712 53550 : if (ol_add(t->columns, &col->base))
1713 : return NULL;
1714 :
1715 53550 : ATOMIC_PTR_INIT(&col->data, NULL);
1716 53550 : if (isTable(col->t))
1717 53550 : store->storage_api.create_col(tr, col);
1718 : return col;
1719 : }
1720 :
1721 : static sql_table *
1722 77744 : create_sql_table_with_id(allocator *sa, sqlid id, const char *name, sht type, bit system, int persistence, int commit_action, bte properties)
1723 : {
1724 77744 : sql_table *t = SA_ZNEW(sa, sql_table);
1725 :
1726 77744 : assert((persistence==SQL_PERSIST ||
1727 : persistence==SQL_DECLARED_TABLE ||
1728 : commit_action || type) && commit_action>=0);
1729 77744 : assert(id);
1730 77744 : base_init(sa, &t->base, id, true, name);
1731 77744 : t->type = type;
1732 77744 : t->system = system;
1733 77744 : t->persistence = (temp_t)persistence;
1734 77744 : t->commit_action = (ca_t)commit_action;
1735 77744 : t->query = NULL;
1736 77744 : t->access = 0;
1737 77744 : t->columns = ol_new(sa, (destroy_fptr) &column_destroy, NULL);
1738 77744 : t->idxs = ol_new(sa, (destroy_fptr) &idx_destroy, NULL);
1739 77744 : t->keys = ol_new(sa, (destroy_fptr) &key_destroy, NULL);
1740 77744 : t->triggers = ol_new(sa, (destroy_fptr) &trigger_destroy, NULL);
1741 77744 : if (isMergeTable(t) || isReplicaTable(t))
1742 635 : t->members = list_new(sa, (fdestroy) &part_destroy);
1743 77744 : t->pkey = NULL;
1744 77744 : t->sz = COLSIZE;
1745 77744 : t->s = NULL;
1746 77744 : t->properties = properties;
1747 77744 : memset(&t->part, 0, sizeof(t->part));
1748 77744 : ATOMIC_PTR_INIT(&t->data, NULL);
1749 77744 : return t;
1750 : }
1751 :
1752 : sql_table *
1753 33479 : create_sql_table(sqlstore *store, allocator *sa, const char *name, sht type, bit system, int persistence, int commit_action, bte properties)
1754 : {
1755 33479 : return create_sql_table_with_id(sa, next_oid(store), name, type, system, persistence, commit_action, properties);
1756 : }
1757 :
1758 : static void
1759 620828 : dup_sql_type(sql_trans *tr, sql_schema *s, sql_subtype *oc, sql_subtype *nc)
1760 : {
1761 620828 : nc->digits = oc->digits;
1762 620828 : nc->scale = oc->scale;
1763 620828 : nc->type = oc->type;
1764 620828 : if (s && nc->type->s) { /* user type */
1765 14312 : sql_type *lt = NULL;
1766 :
1767 14312 : if (s->base.id == nc->type->s->base.id) {
1768 : /* Current user type belongs to current schema. So search there for current user type. */
1769 9208 : lt = find_sql_type(tr, s, nc->type->base.name);
1770 : } else {
1771 : /* Current user type belongs to another schema in the current transaction. Search there for current user type. */
1772 5104 : lt = sql_trans_bind_type(tr, NULL, nc->type->base.name);
1773 : }
1774 14312 : if (lt == NULL)
1775 0 : GDKfatal("SQL type %s missing", nc->type->base.name);
1776 14312 : sql_init_subtype(nc, lt, nc->digits, nc->scale);
1777 : }
1778 620828 : nc->multiset = oc->multiset;
1779 620828 : }
1780 :
1781 : static sql_column *
1782 24463 : dup_sql_column(allocator *sa, sql_table *t, sql_column *c)
1783 : {
1784 24463 : sql_column *col = SA_ZNEW(sa, sql_column);
1785 :
1786 48926 : base_init(sa, &col->base, c->base.id, t->persistence==SQL_DECLARED_TABLE?false:c->base.new, c->base.name);
1787 24463 : col->type = c->type; /* Both types belong to the same transaction, so no dup_sql_type call is needed */
1788 24463 : col->def = NULL;
1789 24463 : if (c->def)
1790 1730 : col->def = SA_STRDUP(sa, c->def);
1791 24463 : col->null = c->null;
1792 24463 : col->colnr = c->colnr;
1793 24463 : col->t = t;
1794 24463 : col->unique = c->unique;
1795 24463 : col->storage_type = NULL;
1796 24463 : if (c->storage_type)
1797 2 : col->storage_type = SA_STRDUP(sa, c->storage_type);
1798 24463 : if (ol_add(t->columns, &col->base))
1799 0 : return NULL;
1800 : return col;
1801 : }
1802 :
1803 : static sql_part *
1804 7 : dup_sql_part(allocator *sa, sql_table *mt, sql_part *op)
1805 : {
1806 7 : sql_part *p = SA_ZNEW(sa, sql_part);
1807 :
1808 14 : base_init(sa, &p->base, op->base.id, mt->persistence==SQL_DECLARED_TABLE?false:op->base.new, op->base.name);
1809 7 : p->with_nills = op->with_nills;
1810 :
1811 7 : if (isRangePartitionTable(mt)) {
1812 3 : p->part.range.minvalue = SA_NEW_ARRAY(sa, char, op->part.range.minlength);
1813 3 : p->part.range.maxvalue = SA_NEW_ARRAY(sa, char, op->part.range.maxlength);
1814 3 : memcpy(p->part.range.minvalue, op->part.range.minvalue, op->part.range.minlength);
1815 3 : memcpy(p->part.range.maxvalue, op->part.range.maxvalue, op->part.range.maxlength);
1816 3 : p->part.range.minlength = op->part.range.minlength;
1817 3 : p->part.range.maxlength = op->part.range.maxlength;
1818 4 : } else if (isListPartitionTable(mt)) {
1819 4 : p->part.values = list_new(sa, (fdestroy) &part_value_destroy);
1820 16 : for (node *n = op->part.values->h ; n ; n = n->next) {
1821 12 : sql_part_value *prev = (sql_part_value*) n->data, *nextv = SA_ZNEW(sa, sql_part_value);
1822 12 : nextv->value = SA_NEW_ARRAY(sa, char, prev->length);
1823 12 : memcpy(nextv->value, prev->value, prev->length);
1824 12 : nextv->length = prev->length;
1825 12 : list_append(p->part.values, nextv);
1826 : }
1827 : }
1828 7 : list_append(mt->members, p);
1829 7 : p->t = mt;
1830 7 : p->member = op->member;
1831 7 : assert(p->member);
1832 7 : return p;
1833 : }
1834 :
1835 : sql_table *
1836 1599 : dup_sql_table(allocator *sa, sql_table *t)
1837 : {
1838 1599 : node *n;
1839 1599 : sql_table *nt = create_sql_table_with_id(sa, t->base.id, t->base.name, t->type, t->system, SQL_DECLARED_TABLE, t->commit_action, t->properties);
1840 :
1841 1599 : nt->base.new = t->base.new;
1842 :
1843 1599 : nt->access = t->access;
1844 1599 : nt->query = (t->query) ? SA_STRDUP(sa, t->query) : NULL;
1845 1599 : nt->s = t->s;
1846 :
1847 1599 : if (isPartitionedByExpressionTable(nt)) {
1848 7 : nt->part.pexp = SA_ZNEW(sa, sql_expression);
1849 7 : nt->part.pexp->exp = SA_STRDUP(sa, t->part.pexp->exp);
1850 7 : nt->part.pexp->type = t->part.pexp->type; /* No dup_sql_type call needed */
1851 7 : nt->part.pexp->cols = SA_LIST(sa, (fdestroy) &int_destroy);
1852 20 : for (n = t->part.pexp->cols->h; n; n = n->next) {
1853 13 : int *nid = SA_NEW(sa, int);
1854 13 : *nid = *(int *) n->data;
1855 13 : list_append(nt->part.pexp->cols, nid);
1856 : }
1857 : }
1858 :
1859 26062 : for (n = t->columns->l->h; n; n = n->next) {
1860 24463 : sql_column *c = n->data;
1861 24463 : sql_column *dup = dup_sql_column(sa, nt, c);
1862 24463 : if (isPartitionedByColumnTable(nt) && c->base.id == t->part.pcol->base.id)
1863 16 : nt->part.pcol = dup;
1864 : }
1865 :
1866 1599 : if (t->members)
1867 37 : for (n = t->members->h; n; n = n->next)
1868 7 : dup_sql_part(sa, nt, n->data);
1869 1599 : return nt;
1870 : }
1871 :
1872 : static sql_table *
1873 7497 : bootstrap_create_table(sql_trans *tr, sql_schema *s, const char *name, sqlid id)
1874 : {
1875 7497 : sqlstore *store = tr->store;
1876 7497 : int istmp = isTempSchema(s);
1877 7497 : int persistence = istmp?SQL_GLOBAL_TEMP:SQL_PERSIST;
1878 5355 : sht commit_action = istmp?CA_PRESERVE:CA_COMMIT;
1879 7497 : sql_table *t;
1880 :
1881 7497 : if ((sqlid) ATOMIC_GET(&store->obj_id) <= id)
1882 1071 : ATOMIC_SET(&store->obj_id, id + 1);
1883 7497 : t = create_sql_table_with_id(NULL, id, name, tt_table, 1, persistence, commit_action, 0);
1884 7497 : t->bootstrap = 1;
1885 :
1886 7497 : TRC_DEBUG(SQL_STORE, "Create table: %s\n", name);
1887 :
1888 7497 : t->base.new = s->base.new;
1889 7497 : t->query = NULL;
1890 7497 : t->s = s;
1891 7497 : if (isTable(t) && store->storage_api.create_del(tr, t) != LOG_OK) {
1892 0 : table_destroy(store, t);
1893 0 : return NULL;
1894 : }
1895 7497 : if (os_add(s->tables, tr, name, &t->base)) {
1896 0 : table_destroy(store, t);
1897 0 : return NULL;
1898 : }
1899 : return t;
1900 : }
1901 :
1902 : static sql_schema *
1903 1071 : bootstrap_create_schema(sql_trans *tr, const char *name, sqlid id, sqlid auth_id, int owner)
1904 : {
1905 1071 : sqlstore *store = tr->store;
1906 1071 : sql_schema *s = ZNEW(sql_schema);
1907 :
1908 1071 : if ((sqlid) ATOMIC_GET(&store->obj_id) <= id)
1909 357 : ATOMIC_SET(&store->obj_id, id + 1);
1910 1071 : TRC_DEBUG(SQL_STORE, "Create schema: %s %d %d\n", name, auth_id, owner);
1911 :
1912 1071 : if (strcmp(name, dt_schema) == 0) {
1913 357 : base_init(NULL, &s->base, (sqlid) FUNC_OIDS - 1, true, name);
1914 : } else {
1915 714 : base_init(NULL, &s->base, id, true, name);
1916 : }
1917 1071 : s->base.new = store->first;
1918 1071 : s->auth_id = auth_id;
1919 1071 : s->owner = owner;
1920 1071 : s->system = TRUE;
1921 1071 : s->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
1922 1071 : s->types = os_new(NULL, (destroy_fptr) &type_destroy, false, true, true, false, store);
1923 1071 : s->funcs = os_new(NULL, (destroy_fptr) &func_destroy, false, false, false, false, store);
1924 1071 : s->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
1925 1071 : s->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
1926 1071 : s->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
1927 1071 : s->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
1928 1071 : s->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
1929 1071 : if (os_add(tr->cat->schemas, tr, s->base.name, &s->base)) {
1930 : return NULL;
1931 : }
1932 1071 : if (isTempSchema(s))
1933 357 : tr->tmp = s;
1934 :
1935 1071 : s->store = tr->store;
1936 1071 : return s;
1937 : }
1938 :
1939 : /* TODO clean this */
1940 : static inline int
1941 68534 : dep_hash(sql_dependency_change *dep)
1942 : {
1943 68534 : return (int) BATatoms[TYPE_int].atomHash(&dep->objid);
1944 : }
1945 :
1946 : static void
1947 177120 : dep_hash_clear(sql_hash *h)
1948 : {
1949 177120 : if (h == NULL || h->sa || h->entries == 0)
1950 : return;
1951 29832 : for (int i = 0; i < h->size; i++) {
1952 28928 : sql_hash_e *e = h->buckets[i];
1953 :
1954 31290 : while (e) {
1955 2362 : sql_hash_e *next = e->chain;
1956 :
1957 2362 : _DELETE(e->value);
1958 2362 : _DELETE(e);
1959 2362 : e = next;
1960 : }
1961 28928 : h->buckets[i] = NULL;
1962 : }
1963 904 : h->entries = 0;
1964 : }
1965 :
1966 : static void
1967 714 : dep_hash_destroy(sql_hash *h)
1968 : {
1969 714 : if (h == NULL || h->sa)
1970 : return;
1971 23496 : for (int i = 0; i < h->size; i++) {
1972 22784 : sql_hash_e *e = h->buckets[i];
1973 :
1974 22784 : while (e) {
1975 0 : sql_hash_e *next = e->chain;
1976 :
1977 0 : _DELETE(e->value);
1978 0 : _DELETE(e);
1979 0 : e = next;
1980 : }
1981 : }
1982 712 : _DELETE(h->buckets);
1983 712 : _DELETE(h);
1984 : }
1985 :
1986 : static sqlstore *
1987 358 : store_load(sqlstore *store, allocator *pa)
1988 : {
1989 358 : sql_trans *tr;
1990 358 : sql_table *t, *types, *functions, *arguments;
1991 358 : sql_schema *s;
1992 358 : lng lng_store_oid;
1993 :
1994 358 : assert(pa);
1995 358 : store->sa = pa;
1996 :
1997 358 : store->first = store->logger_api.log_isnew(store);
1998 :
1999 358 : if (store->first && store->readonly) {
2000 : /* cannot initialize database in readonly mode */
2001 1 : TRC_CRITICAL(SQL_STORE, "Cannot initialize store in readonly mode\n");
2002 1 : return NULL;
2003 : }
2004 :
2005 357 : types_init(store->sa); /* initialize global lists of types and functions, TODO: needs to move */
2006 :
2007 : /* we store some spare oids */
2008 357 : ATOMIC_SET(&store->obj_id, FUNC_OIDS);
2009 :
2010 357 : tr = sql_trans_create(store, NULL, NULL);
2011 357 : if (!tr) {
2012 0 : TRC_CRITICAL(SQL_STORE, "Failed to start a transaction while loading the storage\n");
2013 0 : return NULL;
2014 : }
2015 357 : tr->store = store;
2016 357 : tr->active = 1;
2017 :
2018 : /* for now use malloc and free */
2019 357 : store->active = list_create(NULL);
2020 357 : store->dependencies = hash_new(NULL, 32, (fkeyvalue)&dep_hash);
2021 357 : store->depchanges = hash_new(NULL, 32, (fkeyvalue)&dep_hash);
2022 357 : store->sequences = hash_new(NULL, 32, (fkeyvalue)&seq_hash);
2023 357 : store->seqchanges = list_create(NULL);
2024 357 : if (!store->active || !store->dependencies || !store->depchanges || !store->sequences || !store->seqchanges) {
2025 0 : goto critical;
2026 : }
2027 :
2028 357 : s = bootstrap_create_schema(tr, "sys", 2000, ROLE_SYSADMIN, USER_MONETDB);
2029 357 : if (s == NULL) {
2030 0 : goto critical;
2031 : }
2032 357 : if (!store->first)
2033 127 : s->base.new = 0;
2034 :
2035 714 : if ((t = bootstrap_create_table(tr, s, "schemas", 2001)) == NULL ||
2036 714 : bootstrap_create_column(tr, t, "id", 2002, "int", 31) == NULL ||
2037 714 : bootstrap_create_column(tr, t, "name", 2003, "varchar", 1024) == NULL ||
2038 714 : bootstrap_create_column(tr, t, "authorization", 2004, "int", 31) == NULL ||
2039 714 : bootstrap_create_column(tr, t, "owner", 2005, "int", 31) == NULL ||
2040 357 : bootstrap_create_column(tr, t, "system", 2006, "boolean", 1) == NULL ||
2041 :
2042 714 : (types = t = bootstrap_create_table(tr, s, "types", 2007)) == NULL ||
2043 714 : bootstrap_create_column(tr, t, "id", 2008, "int", 31) == NULL ||
2044 714 : bootstrap_create_column(tr, t, "systemname", 2009, "varchar", 256) == NULL || /* no systemname -> composite */
2045 714 : bootstrap_create_column(tr, t, "sqlname", 2010, "varchar", 1024) == NULL ||
2046 714 : bootstrap_create_column(tr, t, "digits", 2011, "int", 31) == NULL ||
2047 714 : bootstrap_create_column(tr, t, "scale", 2012, "int", 31) == NULL ||
2048 714 : bootstrap_create_column(tr, t, "radix", 2013, "int", 31) == NULL ||
2049 714 : bootstrap_create_column(tr, t, "eclass", 2014, "int", 31) == NULL ||
2050 357 : bootstrap_create_column(tr, t, "schema_id", 2015, "int", 31) == NULL ||
2051 :
2052 714 : (functions = t = bootstrap_create_table(tr, s, "functions", 2016)) == NULL ||
2053 714 : bootstrap_create_column(tr, t, "id", 2017, "int", 31) == NULL ||
2054 714 : bootstrap_create_column(tr, t, "name", 2018, "varchar", 256) == NULL ||
2055 714 : bootstrap_create_column(tr, t, "func", 2019, "varchar", 8196) == NULL ||
2056 714 : bootstrap_create_column(tr, t, "mod", 2020, "varchar", 8196) == NULL ||
2057 :
2058 : /* language asm=0, sql=1, R=2, C=3, J=4 */
2059 714 : bootstrap_create_column(tr, t, "language", 2021, "int", 31) == NULL ||
2060 :
2061 : /* func, proc, aggr or filter */
2062 714 : bootstrap_create_column(tr, t, "type", 2022, "int", 31) == NULL ||
2063 714 : bootstrap_create_column(tr, t, "side_effect", 2023, "boolean", 1) == NULL ||
2064 714 : bootstrap_create_column(tr, t, "varres", 2024, "boolean", 1) == NULL ||
2065 714 : bootstrap_create_column(tr, t, "vararg", 2025, "boolean", 1) == NULL ||
2066 714 : bootstrap_create_column(tr, t, "schema_id", 2026, "int", 31) == NULL ||
2067 714 : bootstrap_create_column(tr, t, "system", 2027, "boolean", 1) == NULL ||
2068 714 : bootstrap_create_column(tr, t, "semantics", 2162, "boolean", 1) == NULL ||
2069 357 : bootstrap_create_column(tr, t, "order_specification", 2167, "tinyint", 7) == NULL ||
2070 :
2071 714 : (arguments = t = bootstrap_create_table(tr, s, "args", 2028)) == NULL ||
2072 714 : bootstrap_create_column(tr, t, "id", 2029, "int", 31) == NULL ||
2073 714 : bootstrap_create_column(tr, t, "func_id", 2030, "int", 31) == NULL ||
2074 714 : bootstrap_create_column(tr, t, "name", 2031, "varchar", 256) == NULL ||
2075 714 : bootstrap_create_column(tr, t, "type", 2032, "varchar", 1024) == NULL ||
2076 714 : bootstrap_create_column(tr, t, "type_digits", 2033, "int", 31) == NULL ||
2077 714 : bootstrap_create_column(tr, t, "type_scale", 2034, "int", 31) == NULL ||
2078 714 : bootstrap_create_column(tr, t, "inout", 2035, "tinyint", 7) == NULL ||
2079 714 : bootstrap_create_column(tr, t, "number", 2036, "int", 31) == NULL ||
2080 357 : bootstrap_create_column(tr, t, "multiset", 2172, "tinyint", 7) == NULL || /* setof (1), array (2) or not (0) */
2081 :
2082 714 : (t = bootstrap_create_table(tr, s, "sequences", 2037)) == NULL ||
2083 714 : bootstrap_create_column(tr, t, "id", 2038, "int", 31) == NULL ||
2084 714 : bootstrap_create_column(tr, t, "schema_id", 2039, "int", 31) == NULL ||
2085 714 : bootstrap_create_column(tr, t, "name", 2040, "varchar", 256) == NULL ||
2086 714 : bootstrap_create_column(tr, t, "start", 2041, "bigint", 63) == NULL ||
2087 714 : bootstrap_create_column(tr, t, "minvalue", 2042, "bigint", 63) == NULL ||
2088 714 : bootstrap_create_column(tr, t, "maxvalue", 2043, "bigint", 63) == NULL ||
2089 714 : bootstrap_create_column(tr, t, "increment", 2044, "bigint", 63) == NULL ||
2090 714 : bootstrap_create_column(tr, t, "cacheinc", 2045, "bigint", 63) == NULL ||
2091 357 : bootstrap_create_column(tr, t, "cycle", 2046, "boolean", 1) == NULL ||
2092 :
2093 714 : (t = bootstrap_create_table(tr, s, "table_partitions", 2047)) == NULL ||
2094 714 : bootstrap_create_column(tr, t, "id", 2048, "int", 31) == NULL ||
2095 714 : bootstrap_create_column(tr, t, "table_id", 2049, "int", 31) == NULL ||
2096 714 : bootstrap_create_column(tr, t, "column_id", 2050, "int", 31) == NULL ||
2097 714 : bootstrap_create_column(tr, t, "expression", 2051, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
2098 357 : bootstrap_create_column(tr, t, "type", 2052, "tinyint", 7) == NULL ||
2099 :
2100 714 : (t = bootstrap_create_table(tr, s, "range_partitions", 2053)) == NULL ||
2101 714 : bootstrap_create_column(tr, t, "table_id", 2054, "int", 31) == NULL ||
2102 714 : bootstrap_create_column(tr, t, "partition_id", 2055, "int", 31) == NULL ||
2103 714 : bootstrap_create_column(tr, t, "minimum", 2056, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
2104 714 : bootstrap_create_column(tr, t, "maximum", 2057, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
2105 357 : bootstrap_create_column(tr, t, "with_nulls", 2058, "boolean", 1) == NULL ||
2106 :
2107 714 : (t = bootstrap_create_table(tr, s, "value_partitions", 2059)) == NULL ||
2108 714 : bootstrap_create_column(tr, t, "table_id", 2060, "int", 31) == NULL ||
2109 714 : bootstrap_create_column(tr, t, "partition_id", 2061, "int", 31) == NULL ||
2110 357 : bootstrap_create_column(tr, t, "value", 2062, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
2111 :
2112 714 : (t = bootstrap_create_table(tr, s, "dependencies", 2063)) == NULL ||
2113 714 : bootstrap_create_column(tr, t, "id", 2064, "int", 31) == NULL ||
2114 714 : bootstrap_create_column(tr, t, "depend_id", 2065, "int", 31) == NULL ||
2115 357 : bootstrap_create_column(tr, t, "depend_type", 2066, "smallint", 15) == NULL ||
2116 :
2117 :
2118 714 : (t = bootstrap_create_table(tr, s, "_tables", 2067)) == NULL ||
2119 714 : bootstrap_create_column(tr, t, "id", 2068, "int", 31) == NULL ||
2120 714 : bootstrap_create_column(tr, t, "name", 2069, "varchar", 1024) == NULL ||
2121 714 : bootstrap_create_column(tr, t, "schema_id", 2070, "int", 31) == NULL ||
2122 714 : bootstrap_create_column(tr, t, "query", 2071, "varchar", 1 << 20) == NULL||
2123 714 : bootstrap_create_column(tr, t, "type", 2072, "smallint", 15) == NULL ||
2124 714 : bootstrap_create_column(tr, t, "system", 2073, "boolean", 1) == NULL ||
2125 714 : bootstrap_create_column(tr, t, "commit_action", 2074, "smallint", 15) == NULL ||
2126 357 : bootstrap_create_column(tr, t, "access", 2075, "smallint", 15) == NULL ||
2127 :
2128 714 : (t = bootstrap_create_table(tr, s, "_columns", 2076)) == NULL ||
2129 714 : bootstrap_create_column(tr, t, "id", 2077, "int", 31) == NULL ||
2130 714 : bootstrap_create_column(tr, t, "name", 2078, "varchar", 1024) == NULL ||
2131 714 : bootstrap_create_column(tr, t, "type", 2079, "varchar", 1024) == NULL ||
2132 714 : bootstrap_create_column(tr, t, "type_digits", 2080, "int", 31) == NULL ||
2133 714 : bootstrap_create_column(tr, t, "type_scale", 2081, "int", 31) == NULL ||
2134 714 : bootstrap_create_column(tr, t, "table_id", 2082, "int", 31) == NULL ||
2135 714 : bootstrap_create_column(tr, t, "default", 2083, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
2136 714 : bootstrap_create_column(tr, t, "null", 2084, "boolean", 1) == NULL ||
2137 714 : bootstrap_create_column(tr, t, "number", 2085, "int", 31) == NULL ||
2138 714 : bootstrap_create_column(tr, t, "storage", 2086, "varchar", 2048) == NULL ||
2139 714 : bootstrap_create_column(tr, t, "column_type", 2168, "tinyint", 7) == NULL ||
2140 357 : bootstrap_create_column(tr, t, "multiset", 2170, "tinyint", 7) == NULL || /* setof (1), array (2) or not (0) */
2141 :
2142 714 : (t = bootstrap_create_table(tr, s, "keys", 2087)) == NULL ||
2143 714 : bootstrap_create_column(tr, t, "id", 2088, "int", 31) == NULL ||
2144 714 : bootstrap_create_column(tr, t, "table_id", 2089, "int", 31) == NULL ||
2145 714 : bootstrap_create_column(tr, t, "type", 2090, "int", 31) == NULL ||
2146 714 : bootstrap_create_column(tr, t, "name", 2091, "varchar", 1024) == NULL ||
2147 714 : bootstrap_create_column(tr, t, "rkey", 2092, "int", 31) == NULL ||
2148 714 : bootstrap_create_column(tr, t, "action", 2093, "int", 31) == NULL ||
2149 357 : bootstrap_create_column(tr, t, "check", 2165, "varchar", 2048) == NULL ||
2150 :
2151 714 : (t = bootstrap_create_table(tr, s, "idxs", 2094)) == NULL ||
2152 714 : bootstrap_create_column(tr, t, "id", 2095, "int", 31) == NULL ||
2153 714 : bootstrap_create_column(tr, t, "table_id", 2096, "int", 31) == NULL ||
2154 714 : bootstrap_create_column(tr, t, "type", 2097, "int", 31) == NULL ||
2155 357 : bootstrap_create_column(tr, t, "name", 2098, "varchar", 1024) == NULL ||
2156 :
2157 714 : (t = bootstrap_create_table(tr, s, "triggers", 2099)) == NULL ||
2158 714 : bootstrap_create_column(tr, t, "id", 2100, "int", 31) == NULL ||
2159 714 : bootstrap_create_column(tr, t, "name", 2101, "varchar", 1024) == NULL ||
2160 714 : bootstrap_create_column(tr, t, "table_id", 2102, "int", 31) == NULL ||
2161 714 : bootstrap_create_column(tr, t, "time", 2103, "smallint", 15) == NULL ||
2162 714 : bootstrap_create_column(tr, t, "orientation", 2104, "smallint", 15) == NULL ||
2163 714 : bootstrap_create_column(tr, t, "event", 2105, "smallint", 15) == NULL ||
2164 714 : bootstrap_create_column(tr, t, "old_name", 2106, "varchar", 1024) == NULL ||
2165 714 : bootstrap_create_column(tr, t, "new_name", 2107, "varchar", 1024) == NULL ||
2166 714 : bootstrap_create_column(tr, t, "condition", 2108, "varchar", 2048) == NULL ||
2167 357 : bootstrap_create_column(tr, t, "statement", 2109, "varchar", 2048) == NULL ||
2168 :
2169 714 : (t = bootstrap_create_table(tr, s, "objects", 2110)) == NULL ||
2170 714 : bootstrap_create_column(tr, t, "id", 2111, "int", 31) == NULL ||
2171 714 : bootstrap_create_column(tr, t, "name", 2112, "varchar", 1024) == NULL ||
2172 714 : bootstrap_create_column(tr, t, "nr", 2113, "int", 31) == NULL ||
2173 357 : bootstrap_create_column(tr, t, "sub", 2163, "int", 31) == NULL) {
2174 0 : goto critical;
2175 : }
2176 :
2177 357 : if ((s = bootstrap_create_schema(tr, "tmp", 2114, ROLE_SYSADMIN, USER_MONETDB)) == NULL) {
2178 0 : goto critical;
2179 : }
2180 357 : store->tmp = s;
2181 :
2182 714 : if ((t = bootstrap_create_table(tr, s, "_tables", 2115)) == NULL ||
2183 714 : bootstrap_create_column(tr, t, "id", 2116, "int", 31) == NULL ||
2184 714 : bootstrap_create_column(tr, t, "name", 2117, "varchar", 1024) == NULL ||
2185 714 : bootstrap_create_column(tr, t, "schema_id", 2118, "int", 31) == NULL ||
2186 714 : bootstrap_create_column(tr, t, "query", 2119, "varchar", 1 << 20) == NULL ||
2187 714 : bootstrap_create_column(tr, t, "type", 2120, "smallint", 15) == NULL ||
2188 714 : bootstrap_create_column(tr, t, "system", 2121, "boolean", 1) == NULL ||
2189 714 : bootstrap_create_column(tr, t, "commit_action", 2122, "smallint", 15) == NULL ||
2190 357 : bootstrap_create_column(tr, t, "access", 2123, "smallint", 15) == NULL ||
2191 :
2192 714 : (t = bootstrap_create_table(tr, s, "_columns", 2124)) == NULL ||
2193 714 : bootstrap_create_column(tr, t, "id", 2125, "int", 31) == NULL ||
2194 714 : bootstrap_create_column(tr, t, "name", 2126, "varchar", 1024) == NULL ||
2195 714 : bootstrap_create_column(tr, t, "type", 2127, "varchar", 1024) == NULL ||
2196 714 : bootstrap_create_column(tr, t, "type_digits", 2128, "int", 31) == NULL ||
2197 714 : bootstrap_create_column(tr, t, "type_scale", 2129, "int", 31) == NULL ||
2198 714 : bootstrap_create_column(tr, t, "table_id", 2130, "int", 31) == NULL ||
2199 714 : bootstrap_create_column(tr, t, "default", 2131, "varchar", STORAGE_MAX_VALUE_LENGTH) == NULL ||
2200 714 : bootstrap_create_column(tr, t, "null", 2132, "boolean", 1) == NULL ||
2201 714 : bootstrap_create_column(tr, t, "number", 2133, "int", 31) == NULL ||
2202 714 : bootstrap_create_column(tr, t, "storage", 2134, "varchar", 2048) == NULL ||
2203 714 : bootstrap_create_column(tr, t, "column_type", 2169, "tinyint", 7) == NULL ||
2204 357 : bootstrap_create_column(tr, t, "multiset", 2171, "tinyint", 7) == NULL || /* setof (1), array (2) or not (0) */
2205 :
2206 714 : (t = bootstrap_create_table(tr, s, "keys", 2135)) == NULL ||
2207 714 : bootstrap_create_column(tr, t, "id", 2136, "int", 31) == NULL ||
2208 714 : bootstrap_create_column(tr, t, "table_id", 2137, "int", 31) == NULL ||
2209 714 : bootstrap_create_column(tr, t, "type", 2138, "int", 31) == NULL ||
2210 714 : bootstrap_create_column(tr, t, "name", 2139, "varchar", 1024) == NULL ||
2211 714 : bootstrap_create_column(tr, t, "rkey", 2140, "int", 31) == NULL ||
2212 714 : bootstrap_create_column(tr, t, "action", 2141, "int", 31) == NULL ||
2213 357 : bootstrap_create_column(tr, t, "check", 2166, "varchar", 2048) == NULL ||
2214 :
2215 714 : (t = bootstrap_create_table(tr, s, "idxs", 2142)) == NULL ||
2216 714 : bootstrap_create_column(tr, t, "id", 2143, "int", 31) == NULL ||
2217 714 : bootstrap_create_column(tr, t, "table_id", 2144, "int", 31) == NULL ||
2218 714 : bootstrap_create_column(tr, t, "type", 2145, "int", 31) == NULL ||
2219 357 : bootstrap_create_column(tr, t, "name", 2146, "varchar", 1024) == NULL ||
2220 :
2221 714 : (t = bootstrap_create_table(tr, s, "triggers", 2147)) == NULL ||
2222 714 : bootstrap_create_column(tr, t, "id", 2148, "int", 31) == NULL ||
2223 714 : bootstrap_create_column(tr, t, "name", 2149, "varchar", 1024) == NULL ||
2224 714 : bootstrap_create_column(tr, t, "table_id", 2150, "int", 31) == NULL ||
2225 714 : bootstrap_create_column(tr, t, "time", 2151, "smallint", 15) == NULL ||
2226 714 : bootstrap_create_column(tr, t, "orientation", 2152, "smallint", 15) == NULL ||
2227 714 : bootstrap_create_column(tr, t, "event", 2153, "smallint", 15) == NULL ||
2228 714 : bootstrap_create_column(tr, t, "old_name", 2154, "varchar", 1024) == NULL ||
2229 714 : bootstrap_create_column(tr, t, "new_name", 2155, "varchar", 1024) == NULL ||
2230 714 : bootstrap_create_column(tr, t, "condition", 2156, "varchar", 2048) == NULL ||
2231 357 : bootstrap_create_column(tr, t, "statement", 2157, "varchar", 2048) == NULL ||
2232 :
2233 714 : (t = bootstrap_create_table(tr, s, "objects", 2158)) == NULL ||
2234 714 : bootstrap_create_column(tr, t, "id", 2159, "int", 31) == NULL ||
2235 714 : bootstrap_create_column(tr, t, "name", 2160, "varchar", 1024) == NULL ||
2236 714 : bootstrap_create_column(tr, t, "nr", 2161, "int", 31) == NULL ||
2237 357 : bootstrap_create_column(tr, t, "sub", 2164, "int", 31) == NULL) {
2238 0 : goto critical;
2239 : }
2240 :
2241 357 : if (bootstrap_create_schema(tr, dt_schema, -1, ROLE_SYSADMIN, USER_MONETDB) == NULL) {
2242 0 : goto critical;
2243 : }
2244 :
2245 357 : if (store->first) {
2246 230 : if (insert_types(tr, types) || insert_functions(tr, functions, funcs, arguments) || insert_schemas(tr)) {
2247 0 : TRC_CRITICAL(SQL_STORE, "Cannot load catalog\n");
2248 0 : sql_trans_destroy(tr);
2249 0 : return NULL;
2250 : }
2251 : } else {
2252 127 : tr->active = 0;
2253 : }
2254 :
2255 357 : if (sql_trans_commit(tr) != SQL_OK) {
2256 0 : TRC_CRITICAL(SQL_STORE, "Cannot commit initial transaction\n");
2257 0 : sql_trans_destroy(tr);
2258 0 : return NULL;
2259 : }
2260 357 : tr->ts = store_timestamp(store);
2261 :
2262 357 : store->logger_api.get_sequence(store, OBJ_SID, &lng_store_oid);
2263 357 : store->prev_oid = (sqlid)lng_store_oid;
2264 357 : if ((sqlid) ATOMIC_GET(&store->obj_id) < store->prev_oid)
2265 127 : ATOMIC_SET(&store->obj_id, store->prev_oid);
2266 :
2267 : /* load remaining schemas, tables, columns etc */
2268 357 : tr->active = 1;
2269 357 : if (!store->first && !load_trans(tr)) {
2270 0 : TRC_CRITICAL(SQL_STORE, "Cannot load catalog tables\n");
2271 0 : sql_trans_destroy(tr);
2272 0 : return NULL;
2273 : }
2274 357 : if (sql_trans_commit(tr) != SQL_OK) {
2275 0 : TRC_CRITICAL(SQL_STORE, "Cannot commit loaded objects transaction\n");
2276 0 : sql_trans_destroy(tr);
2277 0 : return NULL;
2278 : }
2279 357 : tr->active = 0;
2280 357 : sql_trans_destroy(tr);
2281 357 : store->initialized = 1;
2282 357 : return store;
2283 :
2284 0 : critical:
2285 0 : TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
2286 0 : sql_trans_destroy(tr);
2287 0 : return NULL;
2288 : }
2289 :
2290 : sqlstore *
2291 358 : store_init(int debug, store_type store_tpe, int readonly, int singleuser)
2292 : {
2293 358 : allocator *pa;
2294 358 : sqlstore *store = MNEW(sqlstore);
2295 :
2296 358 : if (debug&2)
2297 0 : GDKtracer_set_layer_level("sql_all", "debug");
2298 :
2299 358 : if (!store) {
2300 0 : TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
2301 0 : return NULL;
2302 : }
2303 :
2304 358 : if (!(pa = sa_create(NULL))) {
2305 0 : TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
2306 0 : _DELETE(store);
2307 0 : return NULL;
2308 : }
2309 :
2310 358 : *store = (sqlstore) {
2311 : .readonly = readonly,
2312 : .singleuser = singleuser,
2313 : .debug = debug,
2314 : .transaction = ATOMIC_VAR_INIT(TRANSACTION_ID_BASE),
2315 : .nr_active = ATOMIC_VAR_INIT(0),
2316 : .timestamp = ATOMIC_VAR_INIT(0),
2317 : .lastactive = ATOMIC_VAR_INIT(0),
2318 : .function_counter = ATOMIC_VAR_INIT(0),
2319 : .oldest = ATOMIC_VAR_INIT(0),
2320 : .obj_id = ATOMIC_VAR_INIT(0),
2321 : .sa = pa,
2322 : };
2323 :
2324 358 : (void)store_timestamp(store); /* increment once */
2325 358 : MT_lock_init(&store->lock, "sqlstore_lock");
2326 358 : MT_lock_init(&store->commit, "sqlstore_commit");
2327 358 : MT_lock_init(&store->flush, "sqlstore_flush");
2328 23270 : for(int i = 0; i<NR_TABLE_LOCKS; i++)
2329 22912 : MT_lock_init(&store->table_locks[i], "sqlstore_table");
2330 183654 : for(int i = 0; i<NR_COLUMN_LOCKS; i++)
2331 183296 : MT_lock_init(&store->column_locks[i], "sqlstore_column");
2332 :
2333 358 : MT_lock_set(&store->flush);
2334 358 : MT_lock_set(&store->lock);
2335 :
2336 : /* initialize empty bats */
2337 358 : switch (store_tpe) {
2338 358 : case store_bat:
2339 : case store_mem:
2340 358 : if (bat_utils_init() == -1) {
2341 0 : TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing store\n");
2342 0 : MT_lock_unset(&store->lock);
2343 0 : MT_lock_unset(&store->flush);
2344 0 : store_exit(store);
2345 0 : return NULL;
2346 : }
2347 358 : bat_storage_init(&store->storage_api);
2348 358 : bat_table_init(&store->table_api);
2349 358 : bat_logger_init(&store->logger_api);
2350 358 : break;
2351 : default:
2352 : break;
2353 : }
2354 358 : store->active_type = store_tpe;
2355 358 : int v = 1;
2356 716 : if (!store->logger_api.create ||
2357 358 : store->logger_api.create(store, debug, "sql_logs", CATALOG_VERSION*v) != LOG_OK) {
2358 0 : MT_lock_unset(&store->lock);
2359 0 : MT_lock_unset(&store->flush);
2360 0 : store_exit(store);
2361 0 : return NULL;
2362 : }
2363 :
2364 : /* create the initial store structure or re-load previous data */
2365 358 : MT_lock_unset(&store->lock);
2366 358 : MT_lock_unset(&store->flush);
2367 358 : if (!store_load(store, pa)) {
2368 : /* zap current change list */
2369 1 : store->changes = NULL;
2370 1 : store_exit(store);
2371 1 : return NULL;
2372 : }
2373 : return store;
2374 : }
2375 :
2376 : void
2377 357 : store_exit(sqlstore *store)
2378 : {
2379 357 : allocator *sa = store->sa;
2380 357 : MT_lock_set(&store->commit);
2381 357 : MT_lock_set(&store->flush);
2382 357 : MT_lock_set(&store->lock);
2383 :
2384 357 : TRC_DEBUG(SQL_STORE, "Store locked\n");
2385 :
2386 357 : if (store->cat) {
2387 356 : while (ATOMIC_GET(&store->nr_active) > 0) {
2388 0 : const int sleeptime = 100;
2389 0 : MT_lock_unset(&store->flush);
2390 0 : MT_lock_unset(&store->lock);
2391 0 : MT_lock_unset(&store->commit);
2392 0 : MT_sleep_ms(sleeptime);
2393 0 : MT_lock_set(&store->commit);
2394 0 : MT_lock_set(&store->lock);
2395 356 : MT_lock_set(&store->flush);
2396 : }
2397 356 : if (!list_empty(store->changes)) {
2398 34 : ulng oldest = store_timestamp(store)+1;
2399 95 : for(node *n=store->changes->h; n; n = n->next) {
2400 61 : sql_change *c = n->data;
2401 :
2402 61 : if (c->cleanup && !c->cleanup(store, c, oldest)) {
2403 : /* try again with newer oldest, should cleanup any pending issues */
2404 0 : if (!c->cleanup(store, c, oldest+1))
2405 0 : TRC_DEBUG(SQL_STORE, "not deleted\n");
2406 : else
2407 0 : _DELETE(c);
2408 : } else
2409 61 : _DELETE(c);
2410 : }
2411 : }
2412 356 : MT_lock_unset(&store->commit);
2413 356 : list_destroy(store->changes);
2414 356 : os_destroy(store->cat->objects, store);
2415 356 : os_destroy(store->cat->schemas, store);
2416 356 : _DELETE(store->cat);
2417 : } else {
2418 1 : MT_lock_unset(&store->commit);
2419 : }
2420 357 : store->logger_api.destroy(store);
2421 :
2422 357 : list_destroy(store->active);
2423 357 : dep_hash_destroy(store->dependencies);
2424 357 : dep_hash_destroy(store->depchanges);
2425 357 : list_destroy(store->seqchanges);
2426 357 : seq_hash_destroy(store->sequences);
2427 :
2428 357 : TRC_DEBUG(SQL_STORE, "Store unlocked\n");
2429 357 : MT_lock_unset(&store->flush);
2430 357 : MT_lock_unset(&store->lock);
2431 357 : sa_destroy(sa);
2432 357 : MT_lock_destroy(&store->lock);
2433 357 : MT_lock_destroy(&store->commit);
2434 357 : MT_lock_destroy(&store->flush);
2435 23205 : for(int i = 0; i<NR_TABLE_LOCKS; i++)
2436 22848 : MT_lock_destroy(&store->table_locks[i]);
2437 183141 : for(int i = 0; i<NR_COLUMN_LOCKS; i++)
2438 182784 : MT_lock_destroy(&store->column_locks[i]);
2439 357 : _DELETE(store);
2440 357 : }
2441 :
2442 : /* call locked! */
2443 : static int
2444 1615 : store_apply_deltas(sqlstore *store)
2445 : {
2446 1615 : int res = LOG_OK;
2447 :
2448 1615 : store_lock(store);
2449 1615 : ulng oldest = store_oldest_pending(store);
2450 1615 : store_unlock(store);
2451 1615 : TRC_DEBUG(SQL_STORE, "Store apply deltas (" ULLFMT ")\n", oldest-1);
2452 1615 : if (oldest)
2453 1615 : res = store->logger_api.flush(store, oldest-1);
2454 1615 : return res;
2455 : }
2456 :
2457 : void
2458 0 : store_suspend_log(sqlstore *store)
2459 : {
2460 0 : MT_lock_set(&store->lock);
2461 0 : MT_lock_unset(&store->lock);
2462 0 : }
2463 :
2464 : void
2465 0 : store_resume_log(sqlstore *store)
2466 : {
2467 0 : MT_lock_set(&store->flush);
2468 0 : MT_lock_unset(&store->flush);
2469 0 : }
2470 :
2471 : static void
2472 151070 : id_hash_clear_older(sql_hash *h, ulng oldest)
2473 : {
2474 151070 : if (h->entries == 0)
2475 : return;
2476 1435929 : for (int i = 0; i < h->size; i++) {
2477 1392416 : sql_hash_e *e = h->buckets[i], *last = NULL, *first = NULL;
2478 :
2479 1671247 : while (e) {
2480 278831 : sql_hash_e *next = e->chain;
2481 278831 : sql_dependency_change *dc = e->value;
2482 :
2483 278831 : if (dc->ts < oldest) {
2484 40551 : _DELETE(e->value);
2485 40551 : _DELETE(e);
2486 40551 : h->entries--;
2487 : } else {
2488 238280 : if (last)
2489 93421 : last->chain = e;
2490 : else
2491 : first = e;
2492 : last = e;
2493 : }
2494 : e = next;
2495 : }
2496 1392416 : if (last)
2497 144859 : last->chain = NULL;
2498 1392416 : h->buckets[i] = first;
2499 : }
2500 : }
2501 :
2502 : static void
2503 164095 : store_pending_changes(sqlstore *store, ulng oldest, sql_trans *tr)
2504 : {
2505 164095 : ulng oldest_changes = store_get_timestamp(store);
2506 164095 : if (!list_empty(store->changes)) { /* lets first cleanup old stuff */
2507 862467 : for(node *n=store->changes->h; n; ) {
2508 810397 : node *next = n->next;
2509 810397 : sql_change *c = n->data;
2510 :
2511 810397 : assert(c->cleanup);
2512 810397 : if (c->cleanup(store, c, oldest)) {
2513 183667 : list_remove_node(store->changes, store, n);
2514 183667 : _DELETE(c);
2515 626730 : } else if (!c->handled && c->ts < oldest_changes) {
2516 810397 : oldest_changes = c->ts;
2517 : }
2518 : n = next;
2519 : }
2520 : }
2521 164095 : if (ATOMIC_GET(&store->nr_active) < 2) { /* one or no transaction running */
2522 88560 : dep_hash_clear(store->dependencies);
2523 88560 : dep_hash_clear(store->depchanges);
2524 : } else {
2525 75535 : ulng stoldest = store_oldest(store, tr);
2526 75535 : id_hash_clear_older(store->dependencies, stoldest);
2527 75535 : id_hash_clear_older(store->depchanges, stoldest);
2528 : }
2529 164095 : store->oldest_pending = oldest_changes;
2530 164095 : }
2531 :
2532 : #define IDLE_TIME 30 /* in seconds */
2533 :
2534 : void
2535 356 : store_manager(sqlstore *store)
2536 : {
2537 356 : MT_thread_setworking("sleeping");
2538 :
2539 : // In the main loop we always hold the lock except when sleeping or doing cleanups
2540 356 : MT_lock_set(&store->flush);
2541 :
2542 9216 : for (;;) {
2543 9216 : const int idle = ATOMIC_GET(&GDKdebug) & TESTINGMASK ? 5000 : IDLE_TIME * 1000000;
2544 : /* if debug bit 1024 is set, attempt immediate log activation
2545 : * and clear the bit */
2546 9216 : if (store->debug&(128|1024) || ATOMIC_GET(&store->lastactive) + idle < (ATOMIC_BASE_TYPE) GDKusec()) {
2547 7370 : store->debug &= ~1024;
2548 7370 : MT_lock_unset(&store->flush);
2549 7370 : store_lock(store);
2550 7370 : if (ATOMIC_GET(&store->nr_active) == 0) {
2551 2859 : ulng oldest = store_timestamp(store)+1;
2552 2859 : store_pending_changes(store, oldest, NULL);
2553 : }
2554 7370 : store_unlock(store);
2555 7370 : MT_lock_set(&store->flush);
2556 7370 : store->logger_api.activate(store); /* rotate to new log file */
2557 7370 : ATOMIC_SET(&store->lastactive, GDKusec());
2558 : }
2559 :
2560 9216 : if (GDKexiting())
2561 : break;
2562 9216 : const int sleeptime = 100;
2563 9216 : MT_lock_unset(&store->flush);
2564 9216 : MT_sleep_ms(sleeptime);
2565 9223 : for (;;) {
2566 9219 : MT_lock_set(&store->commit);
2567 9219 : if (MT_lock_try(&store->flush))
2568 : break;
2569 4 : MT_lock_unset(&store->commit);
2570 4 : MT_sleep_ms(sleeptime);
2571 : }
2572 :
2573 9215 : if (GDKexiting()) {
2574 354 : MT_lock_unset(&store->commit);
2575 354 : break;
2576 : }
2577 :
2578 8861 : if (store->logger_api.changes(store) <= 0) {
2579 7246 : TRC_DEBUG(SQL_STORE, "Store flusher, no changes\n");
2580 7246 : MT_lock_unset(&store->commit);
2581 7246 : continue;
2582 : }
2583 1615 : MT_lock_unset(&store->commit);
2584 :
2585 1615 : MT_thread_setworking("flushing");
2586 1615 : if (store_apply_deltas(store) != LOG_OK) {
2587 0 : MT_lock_unset(&store->flush);
2588 0 : if (!GDKexiting())
2589 0 : GDKfatal("write-ahead logging failure");
2590 : }
2591 :
2592 1615 : if (GDKexiting())
2593 : break;
2594 1614 : MT_thread_setworking("sleeping");
2595 1614 : TRC_DEBUG(SQL_STORE, "Store flusher done\n");
2596 : }
2597 :
2598 : // End of loop, end of lock
2599 355 : MT_lock_unset(&store->flush);
2600 355 : }
2601 :
2602 : void
2603 720891 : store_lock(sqlstore *store)
2604 : {
2605 720891 : MT_lock_set(&store->lock);
2606 : /* tell GDK allocation functions to ignore limits */
2607 721321 : MT_thread_setworking("store locked");
2608 721321 : }
2609 :
2610 : void
2611 721321 : store_unlock(sqlstore *store)
2612 : {
2613 721321 : TRC_DEBUG(SQL_STORE, "Store unlocked\n");
2614 : /* tell GDK allocation functions to honor limits again */
2615 721321 : MT_thread_setworking("store unlocked");
2616 721321 : MT_lock_unset(&store->lock);
2617 721315 : }
2618 :
2619 : int
2620 754943 : store_readonly(sqlstore *store)
2621 : {
2622 754943 : return store->readonly;
2623 : }
2624 :
2625 : // Helper function for tar_write_header.
2626 : // Our stream.h makes sure __attribute__ exists.
2627 : __attribute__((__format__(__printf__, 3, 4)))
2628 : static void
2629 16960 : tar_write_header_field(char **cursor_ptr, size_t size, const char *fmt, ...)
2630 : {
2631 16960 : va_list ap;
2632 :
2633 16960 : va_start(ap, fmt);
2634 16960 : (void)vsnprintf(*cursor_ptr, size + 1, fmt, ap);
2635 16960 : va_end(ap);
2636 :
2637 : /* At first reading you might wonder why add `size` instead
2638 : * of the byte count returned by vsnprintf. The reason is
2639 : * that we want to move `*cursor_ptr` to the start of the next
2640 : * field, not to the unused part of this field.
2641 : */
2642 16960 : *cursor_ptr += size;
2643 16960 : }
2644 :
2645 : #define TAR_BLOCK_SIZE (512)
2646 :
2647 : // Write a tar header to the given stream.
2648 : __attribute__((__warn_unused_result__))
2649 : static gdk_return
2650 1060 : tar_write_header(stream *tarfile, const char *path, time_t mtime, int64_t size)
2651 : {
2652 1060 : char buf[TAR_BLOCK_SIZE] = {0};
2653 1060 : char *cursor = buf;
2654 1060 : char *size_field;
2655 1060 : char *chksum_field;
2656 :
2657 : // We set the uid/gid fields to 0 and the uname/gname fields to "".
2658 : // When unpacking as a normal user, they are ignored and the files are
2659 : // owned by that user. When unpacking as root it is reasonable that
2660 : // the resulting files are owned by root.
2661 :
2662 : // The following is taken directly from the definition found
2663 : // in /usr/include/tar.h on a Linux system.
2664 1060 : tar_write_header_field(&cursor, 100, "%s", path); // name[100]
2665 1060 : tar_write_header_field(&cursor, 8, "0000644"); // mode[8]
2666 1060 : tar_write_header_field(&cursor, 8, "%07o", 0U); // uid[8]
2667 1060 : tar_write_header_field(&cursor, 8, "%07o", 0U); // gid[8]
2668 1060 : size_field = cursor;
2669 1060 : cursor += 12; // size[12]
2670 1060 : tar_write_header_field(&cursor, 12, "%011lo", (unsigned long)mtime); // mtime[12]
2671 1060 : chksum_field = cursor; // use this later to set the computed checksum
2672 1060 : tar_write_header_field(&cursor, 8, "%8s", ""); // chksum[8]
2673 1060 : *cursor++ = '0'; // typeflag REGTYPE
2674 1060 : tar_write_header_field(&cursor, 100, "%s", ""); // linkname[100]
2675 1060 : tar_write_header_field(&cursor, 6, "%s", "ustar"); // magic[6]
2676 1060 : tar_write_header_field(&cursor, 2, "%02o", 0U); // version, not null terminated
2677 1060 : tar_write_header_field(&cursor, 32, "%s", ""); // uname[32]
2678 1060 : tar_write_header_field(&cursor, 32, "%s", ""); // gname[32]
2679 1060 : tar_write_header_field(&cursor, 8, "%07o", 0U); // devmajor[8]
2680 1060 : tar_write_header_field(&cursor, 8, "%07o", 0U); // devminor[8]
2681 1060 : tar_write_header_field(&cursor, 155, "%s", ""); // prefix[155]
2682 1060 : assert(cursor - buf == 500);
2683 :
2684 1060 : int64_t max_oct_size = 077777777777; // 0_777_7777_7777, 11 octal digits
2685 : // max_oct_size = 077; // for testing
2686 1060 : if (size <= max_oct_size) {
2687 1060 : tar_write_header_field(&size_field, 12, "%011"PRIo64, size); // size[12]
2688 : } else {
2689 0 : uint8_t *field = (uint8_t *)size_field;
2690 0 : field[0] = 0x80;
2691 0 : for (int i = 11; i >= 4; i--) {
2692 0 : field[i] = size & 0xFF;
2693 0 : size >>= 8;
2694 : }
2695 : }
2696 :
2697 : // checksum
2698 1060 : unsigned sum = 0;
2699 543780 : for (int i = 0; i < TAR_BLOCK_SIZE; i++)
2700 542720 : sum += (unsigned char) buf[i];
2701 :
2702 1060 : tar_write_header_field(&chksum_field, 8, "%06o", sum);
2703 :
2704 1060 : if (mnstr_write(tarfile, buf, TAR_BLOCK_SIZE, 1) != 1) {
2705 0 : GDKerror("error writing tar header %s: %s", path, mnstr_peek_error(tarfile));
2706 0 : return GDK_FAIL;
2707 : }
2708 :
2709 : return GDK_SUCCEED;
2710 : }
2711 :
2712 : /* Write data to the stream, padding it with zeroes up to the next
2713 : * multiple of TAR_BLOCK_SIZE. Make sure all writes are in multiples
2714 : * of TAR_BLOCK_SIZE.
2715 : */
2716 : __attribute__((__warn_unused_result__))
2717 : static gdk_return
2718 1075 : tar_write(stream *outfile, const char *path, const char *data, size_t size)
2719 : {
2720 1075 : const size_t tail = size % TAR_BLOCK_SIZE;
2721 1075 : const size_t bulk = size - tail;
2722 :
2723 1075 : if (bulk) {
2724 510 : size_t written = mnstr_write(outfile, data, 1, bulk);
2725 510 : if (written != bulk) {
2726 0 : GDKerror("Wrote only %zu bytes of %s instead of first %zu", written, path, bulk);
2727 0 : return GDK_FAIL;
2728 : }
2729 : }
2730 :
2731 1075 : if (tail) {
2732 1035 : char buf[TAR_BLOCK_SIZE] = {0};
2733 1035 : memcpy(buf, data + bulk, tail);
2734 1035 : size_t written = mnstr_write(outfile, buf, 1, TAR_BLOCK_SIZE);
2735 1035 : if (written != TAR_BLOCK_SIZE) {
2736 0 : GDKerror("Wrote only %zu tail bytes of %s instead of %d", written, path, TAR_BLOCK_SIZE);
2737 0 : return GDK_FAIL;
2738 : }
2739 : }
2740 :
2741 : return GDK_SUCCEED;
2742 : }
2743 :
2744 : __attribute__((__warn_unused_result__))
2745 : static gdk_return
2746 15 : tar_write_data(stream *tarfile, const char *path, time_t mtime, const char *data, size_t size)
2747 : {
2748 15 : gdk_return res;
2749 :
2750 15 : res = tar_write_header(tarfile, path, mtime, size);
2751 15 : if (res != GDK_SUCCEED)
2752 : return res;
2753 :
2754 15 : return tar_write(tarfile, path, data, size);
2755 : }
2756 :
2757 : __attribute__((__warn_unused_result__))
2758 : static gdk_return
2759 1045 : tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream *contents, int64_t size, char *buf, size_t bufsize)
2760 : {
2761 1045 : assert( (bufsize % TAR_BLOCK_SIZE) == 0);
2762 1045 : assert(bufsize >= TAR_BLOCK_SIZE);
2763 :
2764 1045 : if (tar_write_header(tarfile, path, mtime, size) != GDK_SUCCEED)
2765 : return GDK_FAIL;
2766 :
2767 : int64_t to_do = size;
2768 2095 : while (to_do > 0) {
2769 1050 : size_t chunk = (to_do <= (int64_t)bufsize) ? (size_t)to_do : bufsize;
2770 1050 : ssize_t nbytes = mnstr_read(contents, buf, 1, chunk);
2771 1050 : if (nbytes > 0) {
2772 1050 : if (tar_write(tarfile, path, buf, nbytes) != GDK_SUCCEED)
2773 : return GDK_FAIL;
2774 1050 : to_do -= (int64_t)nbytes;
2775 1050 : continue;
2776 : }
2777 : // error handling
2778 0 : if (nbytes < 0) {
2779 0 : GDKerror("Error after reading %"PRId64"/%"PRId64" bytes: %s",
2780 : size - to_do, size, mnstr_peek_error(contents));
2781 0 : return GDK_FAIL;
2782 : } else {
2783 0 : GDKerror("Unexpected end of file after reading %"PRId64"/%"PRId64" bytes of %s",
2784 : size - to_do, size, path);
2785 0 : return GDK_FAIL;
2786 : }
2787 : }
2788 :
2789 : return GDK_SUCCEED;
2790 : }
2791 :
2792 : __attribute__((__warn_unused_result__))
2793 : static gdk_return
2794 5 : hot_snapshot_write_tar(stream *out, const char *prefix, const char *plan)
2795 : {
2796 5 : if (plan == NULL)
2797 : return GDK_FAIL;
2798 :
2799 5 : gdk_return ret = GDK_FAIL;
2800 5 : const char *p = plan; // our cursor in the plan
2801 5 : time_t timestamp = 1234567890; // dummy date, Sat 14 Feb 2009 12:31:30 AM CET
2802 : // Name convention: _path for the absolute path
2803 : // and _name for the corresponding local relative path
2804 5 : char abs_src_path[2 * FILENAME_MAX];
2805 5 : char *src_name = abs_src_path;
2806 5 : char dest_path[100]; // size imposed by tar format.
2807 5 : char *dest_name = dest_path + snprintf(dest_path, sizeof(dest_path), "%s/", prefix);
2808 5 : stream *infile = NULL;
2809 5 : const char *bufsize_env_var = "hot_snapshot_buffer_size";
2810 5 : int bufsize = GDKgetenv_int(bufsize_env_var, 1024 * 1024);
2811 5 : char *buffer = NULL;
2812 :
2813 5 : if (bufsize < TAR_BLOCK_SIZE || (bufsize % TAR_BLOCK_SIZE) != 0) {
2814 0 : GDKerror("invalid value for setting %s=%d: must be a multiple of %d",
2815 : bufsize_env_var, bufsize, TAR_BLOCK_SIZE);
2816 0 : goto end;
2817 : }
2818 5 : buffer = GDKmalloc(bufsize);
2819 5 : if (!buffer) {
2820 0 : GDKerror("could not allocate buffer");
2821 0 : goto end;
2822 : }
2823 :
2824 5 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
2825 :
2826 5 : int len;
2827 5 : if (sscanf(p, "%[^\n]\n%n", abs_src_path, &len) != 1) {
2828 0 : GDKerror("internal error: first line of plan is malformed");
2829 0 : goto end;
2830 : }
2831 5 : p += len;
2832 5 : src_name = abs_src_path + len - 1; // - 1 because len includes the trailing newline
2833 5 : *src_name++ = DIR_SEP;
2834 :
2835 : // When testing it's sometimes useful to include the plan in the snapshot file
2836 : // strcpy(dest_name, "_snapshot.plan");
2837 : // if (tar_write_data(out, dest_path, timestamp, plan, strlen(plan)) != GDK_SUCCEED)
2838 : // goto end;
2839 :
2840 5 : char command;
2841 5 : int64_t size;
2842 1065 : while (sscanf(p, "%c %"SCNi64" %100s\n%n", &command, &size, src_name, &len) == 3) {
2843 1060 : GDK_CHECK_TIMEOUT_BODY(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(end, qry_ctx));
2844 1060 : p += len;
2845 1060 : strcpy(dest_name, src_name);
2846 1060 : if (size < 0) {
2847 0 : GDKerror("malformed snapshot plan for %s: size %"PRId64" < 0", src_name, size);
2848 0 : goto end;
2849 : }
2850 1060 : switch (command) {
2851 1045 : case 'c':
2852 1045 : infile = open_rstream(abs_src_path);
2853 1045 : if (!infile) {
2854 0 : GDKerror("%s", mnstr_peek_error(NULL));
2855 0 : goto end;
2856 : }
2857 1045 : if (tar_copy_stream(out, dest_path, timestamp, infile, size, buffer, (size_t)bufsize) != GDK_SUCCEED)
2858 0 : goto end;
2859 1045 : close_stream(infile);
2860 1045 : infile = NULL;
2861 1045 : break;
2862 15 : case 'w':
2863 15 : if (tar_write_data(out, dest_path, timestamp, p, (size_t)size) != GDK_SUCCEED)
2864 0 : goto end;
2865 15 : p += (size_t)size;
2866 15 : break;
2867 0 : default:
2868 0 : GDKerror("Unknown command in snapshot plan: %c (%s)", command, src_name);
2869 0 : goto end;
2870 : }
2871 1060 : mnstr_flush(out, MNSTR_FLUSH_ALL);
2872 : }
2873 :
2874 : // write a trailing block of zeros. If it succeeds, this function succeeds.
2875 5 : char *descr = "end-of-archive marker";
2876 5 : char a;
2877 5 : a = '\0';
2878 5 : ret = tar_write(out, descr, &a, 1);
2879 5 : if (ret == GDK_SUCCEED)
2880 5 : ret = tar_write(out, descr, &a, 1);
2881 :
2882 0 : end:
2883 5 : free((char*)plan);
2884 5 : GDKfree(buffer);
2885 5 : if (infile)
2886 0 : close_stream(infile);
2887 : return ret;
2888 : }
2889 :
2890 : /* Pick a name for the temporary tar file. Make sure it has the same extension
2891 : * so as not to confuse the streams library.
2892 : *
2893 : * This function is not entirely safe as compared to for example mkstemp.
2894 : */
2895 : __attribute__((__warn_unused_result__))
2896 : static str
2897 5 : pick_tmp_name(str filename)
2898 : {
2899 5 : str name = GDKmalloc(strlen(filename) + 10);
2900 5 : if (name == NULL) {
2901 0 : GDKerror("malloc failed");
2902 0 : return NULL;
2903 : }
2904 5 : strcpy(name, filename);
2905 :
2906 : // Look for an extension.
2907 : // Make sure it's part of the basename
2908 :
2909 5 : char *ext = strrchr(name, '.');
2910 5 : char *sep = strrchr(name, DIR_SEP);
2911 5 : char *slash = strrchr(name, '/'); // on Windows, / and \ both work
2912 5 : if (ext != NULL) {
2913 : // is ext actually after sep and slash?
2914 5 : if ((sep != NULL && sep > ext) || (slash != NULL && slash > ext))
2915 : ext = NULL;
2916 : }
2917 :
2918 5 : if (ext == NULL) {
2919 0 : return strcat(name, "..tmp");
2920 : } else {
2921 5 : const char tmp[] = "..tmp.";
2922 5 : size_t tmplen = strlen(tmp);
2923 5 : memmove(ext + tmplen, ext, strlen(ext) + 1);
2924 5 : memmove(ext, tmp, tmplen);
2925 : }
2926 :
2927 5 : return name;
2928 : }
2929 :
2930 : lng
2931 5 : store_hot_snapshot_to_stream(sqlstore *store, stream *tar_stream)
2932 : {
2933 5 : int locked = 0;
2934 5 : lng result = 0;
2935 5 : buffer *plan_buf = NULL;
2936 5 : stream *plan_stream = NULL;
2937 5 : gdk_return r;
2938 :
2939 5 : if (!store->logger_api.get_snapshot_files) {
2940 0 : GDKerror("backend does not support hot snapshots");
2941 0 : goto end;
2942 : }
2943 :
2944 5 : plan_buf = buffer_create(64 * 1024);
2945 5 : if (!plan_buf) {
2946 0 : GDKerror("Failed to allocate plan buffer");
2947 0 : goto end;
2948 : }
2949 5 : plan_stream = buffer_wastream(plan_buf, "write_snapshot_plan");
2950 5 : if (!plan_stream) {
2951 0 : GDKerror("Failed to allocate buffer stream");
2952 0 : goto end;
2953 : }
2954 :
2955 5 : MT_lock_set(&store->flush);
2956 5 : MT_lock_set(&store->lock);
2957 5 : BBPtmlock();
2958 5 : locked = 1;
2959 5 : if (GDKexiting())
2960 0 : goto end;
2961 :
2962 5 : r = store->logger_api.get_snapshot_files(store, plan_stream);
2963 5 : if (r != GDK_SUCCEED)
2964 0 : goto end; // should already have set a GDK error
2965 5 : close_stream(plan_stream);
2966 5 : plan_stream = NULL;
2967 5 : MT_lock_unset(&store->lock);
2968 5 : locked = 2;
2969 5 : r = hot_snapshot_write_tar(tar_stream, GDKgetenv("gdk_dbname"), buffer_get_buf(plan_buf));
2970 5 : if (r != GDK_SUCCEED)
2971 0 : goto end;
2972 :
2973 : // the original idea was to return a sort of sequence number of the
2974 : // database that identifies exactly which version has been snapshotted
2975 : // but no such number is available:
2976 : // logger_functions.read_last_transaction_id is not implemented
2977 : // anywhere.
2978 : //
2979 : // So we return a random positive integer instead.
2980 : result = 42;
2981 :
2982 5 : end:
2983 5 : if (locked) {
2984 5 : BBPtmunlock();
2985 5 : if (locked == 1)
2986 0 : MT_lock_unset(&store->lock);
2987 5 : MT_lock_unset(&store->flush);
2988 : }
2989 5 : if (plan_stream)
2990 0 : close_stream(plan_stream);
2991 5 : if (plan_buf)
2992 5 : buffer_destroy(plan_buf);
2993 5 : return result;
2994 : }
2995 :
2996 :
2997 : lng
2998 5 : store_hot_snapshot(sqlstore *store, str tarfile)
2999 : {
3000 5 : lng result = 0;
3001 5 : struct stat st = {0};
3002 5 : char *tmppath = NULL;
3003 5 : char *dirpath = NULL;
3004 5 : int do_remove = 0;
3005 5 : int dir_fd = -1;
3006 5 : stream *tar_stream = NULL;
3007 5 : buffer *plan_buf = NULL;
3008 5 : stream *plan_stream = NULL;
3009 :
3010 5 : if (!store->logger_api.get_snapshot_files) {
3011 0 : GDKerror("backend does not support hot snapshots");
3012 0 : goto end;
3013 : }
3014 :
3015 5 : if (!MT_path_absolute(tarfile)) {
3016 0 : GDKerror("Hot snapshot requires an absolute path");
3017 0 : goto end;
3018 : }
3019 :
3020 5 : if (MT_stat(tarfile, &st) == 0) {
3021 0 : GDKerror("File already exists: %s", tarfile);
3022 0 : goto end;
3023 : }
3024 :
3025 5 : tmppath = pick_tmp_name(tarfile);
3026 5 : if (tmppath == NULL) {
3027 0 : goto end;
3028 : }
3029 5 : tar_stream = open_wstream(tmppath);
3030 5 : if (!tar_stream) {
3031 0 : GDKerror("%s", mnstr_peek_error(NULL));
3032 0 : goto end;
3033 : }
3034 5 : do_remove = 1;
3035 :
3036 : #ifdef HAVE_FSYNC
3037 : // The following only makes sense on POSIX, where fsync'ing a file
3038 : // guarantees the bytes of the file to go to disk, but not necessarily
3039 : // guarantees the existence of the file in a directory to be persistent.
3040 : // Hence the fsync-the-parent ceremony.
3041 :
3042 : // Set dirpath to the directory containing the tar file.
3043 : // Call realpath(2) to make the path absolute so it has at least
3044 : // one DIR_SEP in it. Realpath requires the file to exist so
3045 : // we feed it tmppath rather than tarfile.
3046 5 : dirpath = GDKmalloc(PATH_MAX);
3047 5 : if (dirpath == NULL) {
3048 0 : GDKsyserror("malloc failed");
3049 0 : goto end;
3050 : }
3051 5 : if (realpath(tmppath, dirpath) == NULL) {
3052 0 : GDKsyserror("couldn't resolve path %s: %s", tarfile, strerror(errno));
3053 0 : goto end;
3054 : }
3055 5 : *strrchr(dirpath, DIR_SEP) = '\0';
3056 :
3057 : // Open the directory so we can call fsync on it.
3058 : // We use raw posix calls because this is not available in the streams library
3059 : // and I'm not quite sure what a generic streams-api should look like.
3060 5 : dir_fd = open(dirpath, O_RDONLY); // ERROR no o_rdonly
3061 5 : if (dir_fd < 0) {
3062 0 : GDKsyserror("couldn't open directory %s", dirpath);
3063 0 : goto end;
3064 : }
3065 :
3066 : // Fsync the directory beforehand too.
3067 : // Postgres believes this is necessary for durability.
3068 5 : if (fsync(dir_fd) < 0) {
3069 0 : GDKsyserror("First fsync on %s failed", dirpath);
3070 0 : goto end;
3071 : }
3072 : #else
3073 : (void)dirpath;
3074 : #endif
3075 :
3076 5 : result = store_hot_snapshot_to_stream(store, tar_stream);
3077 5 : if (result == 0)
3078 0 : goto end;
3079 :
3080 : // Now sync and atomically rename the temp file to the real file,
3081 : // also fsync'ing the directory
3082 5 : mnstr_fsync(tar_stream);
3083 5 : close_stream(tar_stream);
3084 5 : tar_stream = NULL;
3085 5 : if (MT_rename(tmppath, tarfile) < 0) {
3086 0 : GDKsyserror("rename %s to %s failed", tmppath, tarfile);
3087 0 : goto end;
3088 : }
3089 5 : do_remove = 0;
3090 : #ifdef HAVE_FSYNC
3091 : // More POSIX fsync-the-parent-dir ceremony
3092 5 : if (fsync(dir_fd) < 0) {
3093 0 : GDKsyserror("fsync on dir %s failed", dirpath);
3094 0 : goto end;
3095 : }
3096 : #endif
3097 5 : end:
3098 5 : GDKfree(dirpath);
3099 5 : if (dir_fd >= 0)
3100 5 : close(dir_fd);
3101 5 : if (tar_stream)
3102 0 : close_stream(tar_stream);
3103 5 : if (plan_stream)
3104 : close_stream(plan_stream);
3105 5 : if (plan_buf)
3106 : buffer_destroy(plan_buf);
3107 5 : if (do_remove)
3108 0 : (void) MT_remove(tmppath); // Best effort, ignore the result
3109 5 : GDKfree(tmppath);
3110 5 : return result;
3111 : }
3112 :
3113 : static int
3114 59219 : column_dup(sql_trans *tr, sql_column *oc, sql_table *t, sql_column **cres)
3115 : {
3116 59219 : sqlstore *store = tr->store;
3117 59219 : sql_column *c = ZNEW(sql_column);
3118 59219 : int res = LOG_OK;
3119 :
3120 59219 : base_init(NULL, &c->base, oc->base.id, 0, oc->base.name);
3121 59219 : c->type = oc->type;
3122 59219 : c->def = NULL;
3123 59219 : if (oc->def)
3124 520 : c->def =_STRDUP(oc->def);
3125 59219 : c->null = oc->null;
3126 59219 : c->colnr = oc->colnr;
3127 59219 : c->unique = oc->unique;
3128 59219 : c->t = t;
3129 59219 : c->storage_type = NULL;
3130 59219 : if (oc->storage_type)
3131 85 : c->storage_type =_STRDUP(oc->storage_type);
3132 59219 : ATOMIC_PTR_INIT(&c->data, NULL);
3133 :
3134 59219 : if (isTable(c->t)) {
3135 58048 : if (isTempTable(c->t)) {
3136 38453 : if ((res = store->storage_api.create_col(tr, c))) {
3137 : return res;
3138 : }
3139 : } else {
3140 19595 : ATOMIC_PTR_SET(&c->data, store->storage_api.col_dup(oc));
3141 : }
3142 : }
3143 59219 : *cres = c;
3144 59219 : return res;
3145 : }
3146 :
3147 : static sql_kc *
3148 21510 : kc_dup(sql_kc *kc, sql_table *t)
3149 : {
3150 21510 : sql_kc *nkc = ZNEW(sql_kc);
3151 21510 : sql_column *c = find_sql_column(t, kc->c->base.name);
3152 :
3153 21510 : assert(c);
3154 21510 : nkc->c = c;
3155 21510 : c->unique = kc->c->unique;
3156 21510 : return nkc;
3157 : }
3158 :
3159 : static int
3160 8797 : key_dup(sql_trans *tr, sql_key *k, sql_table *t, sql_key **kres)
3161 : {
3162 8797 : sql_key *nk = (k->type != fkey) ? (sql_key *) ZNEW(sql_ukey) : (sql_key *) ZNEW(sql_fkey);
3163 8797 : node *n;
3164 8797 : int res = LOG_OK;
3165 :
3166 8797 : base_init(NULL, &nk->base, k->base.id?k->base.id:next_oid(tr->store), 0, k->base.name);
3167 8797 : nk->type = k->type;
3168 8797 : nk->columns = list_create((fdestroy) &kc_destroy);
3169 8797 : nk->t = t;
3170 8797 : nk->idx = NULL;
3171 :
3172 8797 : if (k->idx) {
3173 8743 : node *n = ol_find_name(t->idxs, nk->base.name);
3174 8743 : nk->idx = (sql_idx *)n->data;
3175 8743 : nk->idx->key = nk;
3176 : }
3177 :
3178 8797 : if (nk->type != fkey) {
3179 6885 : sql_ukey *tk = (sql_ukey *) nk;
3180 :
3181 6885 : if (nk->type == pkey)
3182 4632 : t->pkey = tk;
3183 :
3184 6885 : if (nk->type == ckey)
3185 54 : nk->check = _STRDUP(k->check);
3186 : } else {
3187 1912 : sql_fkey *fk = (sql_fkey *) nk;
3188 1912 : sql_fkey *ok = (sql_fkey *) k;
3189 :
3190 1912 : fk->rkey = ok->rkey;
3191 1912 : fk->on_delete = ok->on_delete;
3192 1912 : fk->on_update = ok->on_update;
3193 : }
3194 :
3195 18614 : for (n = k->columns->h; n; n = n->next) {
3196 9817 : sql_kc *okc = n->data;
3197 :
3198 9817 : list_append(nk->columns, kc_dup(okc, t));
3199 : }
3200 :
3201 8797 : if (isGlobal(t) &&
3202 8730 : ((res = os_add(t->s->keys, tr, nk->base.name, dup_base(&nk->base))) ||
3203 8730 : (res = os_add(tr->cat->objects, tr, nk->base.name, dup_base(&nk->base))))) {
3204 0 : return res;
3205 : }
3206 8797 : *kres = nk;
3207 8797 : return res;
3208 : }
3209 :
3210 : static int
3211 3242 : idx_dup(sql_trans *tr, sql_idx * i, sql_table *t, sql_idx **ires)
3212 : {
3213 3242 : sqlstore *store = tr->store;
3214 3242 : sql_idx *ni = ZNEW(sql_idx);
3215 3242 : node *n;
3216 3242 : int res = LOG_OK;
3217 :
3218 3242 : base_init(NULL, &ni->base, i->base.id, 0, i->base.name);
3219 :
3220 3242 : ni->columns = list_create((fdestroy) &kc_destroy);
3221 3242 : ni->t = t;
3222 3242 : ni->type = i->type;
3223 3242 : ni->key = NULL;
3224 3242 : ATOMIC_PTR_INIT(&ni->data, NULL);
3225 :
3226 3242 : if (isTable(i->t)) {
3227 3189 : if (isTempTable(i->t)) {
3228 86 : if ((res = store->storage_api.create_idx(tr, ni))) {
3229 : return res;
3230 : }
3231 : } else {
3232 3103 : ATOMIC_PTR_SET(&ni->data, store->storage_api.idx_dup(i));
3233 : }
3234 : }
3235 :
3236 6935 : for (n = i->columns->h; n; n = n->next) {
3237 3693 : sql_kc *okc = n->data;
3238 :
3239 3693 : list_append(ni->columns, kc_dup(okc, t));
3240 : }
3241 3242 : if (isGlobal(t) && (res = os_add(t->s->idxs, tr, ni->base.name, dup_base(&ni->base)))) {
3242 : return res;
3243 : }
3244 3242 : *ires = ni;
3245 3242 : return res;
3246 : }
3247 :
3248 : static int
3249 504 : part_dup(sql_trans *tr, sql_part *op, sql_table *mt, sql_part **pres)
3250 : {
3251 504 : sql_part *p = ZNEW(sql_part);
3252 504 : int res = LOG_OK;
3253 :
3254 504 : assert(isMergeTable(mt) || isReplicaTable(mt));
3255 504 : base_init(NULL, &p->base, op->base.id, 0, op->base.name);
3256 504 : p->with_nills = op->with_nills;
3257 504 : p->t = mt;
3258 504 : p->member = op->member;
3259 :
3260 504 : if (isRangePartitionTable(mt)) {
3261 262 : p->part.range.minvalue = NEW_ARRAY(char, op->part.range.minlength);
3262 262 : p->part.range.maxvalue = NEW_ARRAY(char, op->part.range.maxlength);
3263 262 : memcpy(p->part.range.minvalue, op->part.range.minvalue, op->part.range.minlength);
3264 262 : memcpy(p->part.range.maxvalue, op->part.range.maxvalue, op->part.range.maxlength);
3265 262 : p->part.range.minlength = op->part.range.minlength;
3266 262 : p->part.range.maxlength = op->part.range.maxlength;
3267 242 : } else if (isListPartitionTable(mt)) {
3268 62 : p->part.values = list_create((fdestroy) &part_value_destroy);
3269 243 : for (node *n = op->part.values->h ; n ; n = n->next) {
3270 181 : sql_part_value *prev = (sql_part_value*) n->data, *nextv = ZNEW(sql_part_value);
3271 181 : nextv->value = NEW_ARRAY(char, prev->length);
3272 181 : memcpy(nextv->value, prev->value, prev->length);
3273 181 : nextv->length = prev->length;
3274 181 : list_append(p->part.values, nextv);
3275 : }
3276 : }
3277 504 : if (isGlobal(mt) && (res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
3278 : return res;
3279 504 : *pres = p;
3280 504 : return res;
3281 : }
3282 :
3283 : static int
3284 128 : trigger_dup(sql_trans *tr, sql_trigger *i, sql_table *t, sql_trigger **tres)
3285 : {
3286 128 : sql_trigger *nt = ZNEW(sql_trigger);
3287 128 : int res = LOG_OK;
3288 :
3289 128 : base_init(NULL, &nt->base, i->base.id, 0, i->base.name);
3290 :
3291 128 : nt->columns = list_create((fdestroy) &kc_destroy);
3292 128 : nt->t = t;
3293 128 : nt->time = i->time;
3294 128 : nt->orientation = i->orientation;
3295 128 : nt->event = i->event;
3296 128 : nt->old_name = nt->new_name = nt->condition = NULL;
3297 128 : if (i->old_name)
3298 39 : nt->old_name =_STRDUP(i->old_name);
3299 128 : if (i->new_name)
3300 55 : nt->new_name =_STRDUP(i->new_name);
3301 128 : if (i->condition)
3302 0 : nt->condition =_STRDUP(i->condition);
3303 128 : nt->statement =_STRDUP(i->statement);
3304 :
3305 128 : for (node *n = i->columns->h; n; n = n->next) {
3306 0 : sql_kc *okc = n->data;
3307 :
3308 0 : list_append(nt->columns, kc_dup(okc, t));
3309 : }
3310 128 : if (isGlobal(t) && (res = os_add(t->s->triggers, tr, nt->base.name, dup_base(&nt->base))))
3311 : return res;
3312 128 : *tres = nt;
3313 128 : return res;
3314 : }
3315 :
3316 : static int
3317 6838 : table_dup(sql_trans *tr, sql_table *ot, sql_schema *s, const char *name,
3318 : sql_table **tres, bool dup_global_as_global)
3319 : {
3320 6838 : sqlstore *store = tr->store;
3321 6838 : sql_table *t = ZNEW(sql_table);
3322 6838 : node *n;
3323 6838 : int res = LOG_OK;
3324 :
3325 6838 : if (t == NULL)
3326 : return LOG_ERR;
3327 6838 : base_init(NULL, &t->base, ot->base.id, 0, name?name:ot->base.name);
3328 6838 : t->type = ot->type;
3329 6838 : t->system = ot->system;
3330 6838 : t->bootstrap = ot->bootstrap;
3331 6838 : t->persistence = (s || dup_global_as_global)?ot->persistence:SQL_LOCAL_TEMP;
3332 6838 : t->commit_action = ot->commit_action;
3333 6838 : t->access = ot->access;
3334 6838 : t->query = (ot->query) ?_STRDUP(ot->query) : NULL;
3335 6838 : t->properties = ot->properties;
3336 6838 : t->multiset = ot->multiset;
3337 6838 : t->composite = ot->composite;
3338 :
3339 6838 : t->columns = ol_new(NULL, (destroy_fptr) &column_destroy, store);
3340 6838 : t->idxs = ol_new(NULL, (destroy_fptr) &idx_destroy, store);
3341 6838 : t->keys = ol_new(NULL, (destroy_fptr) &key_destroy, store);
3342 6838 : t->triggers = ol_new(NULL, (destroy_fptr) &trigger_destroy, store);
3343 6838 : if (ot->members)
3344 578 : t->members = list_create((fdestroy) &part_destroy);
3345 :
3346 6838 : t->pkey = NULL;
3347 6838 : t->s = s ? s : tr->tmp;
3348 6838 : t->sz = ot->sz;
3349 6838 : ATOMIC_PTR_INIT(&t->data, NULL);
3350 :
3351 6838 : if (isPartitionedByExpressionTable(ot)) {
3352 50 : t->part.pexp = ZNEW(sql_expression);
3353 50 : t->part.pexp->exp =_STRDUP(ot->part.pexp->exp);
3354 50 : t->part.pexp->type = ot->part.pexp->type;
3355 50 : t->part.pexp->cols = list_create((fdestroy) &int_destroy);
3356 107 : for (n = ot->part.pexp->cols->h; n; n = n->next) {
3357 57 : int *nid = MNEW(int);
3358 57 : *nid = *(int *) n->data;
3359 57 : list_append(t->part.pexp->cols, nid);
3360 : }
3361 : }
3362 6838 : if (ot->columns)
3363 66057 : for (n = ol_first_node(ot->columns); n; n = n->next) {
3364 59219 : sql_column *c = NULL;
3365 :
3366 59219 : if ((res = column_dup(tr, n->data, t, &c)) || (res = ol_add(t->columns, &c->base)))
3367 0 : goto cleanup;
3368 59219 : if (isPartitionedByColumnTable(ot) && ot->part.pcol->base.id == c->base.id)
3369 250 : t->part.pcol = c;
3370 : }
3371 6838 : if (ot->idxs)
3372 10080 : for (n = ol_first_node(ot->idxs); n; n = n->next) {
3373 3242 : sql_idx *i = NULL;
3374 :
3375 3242 : if ((res = idx_dup(tr, n->data, t, &i)) || (res = ol_add(t->idxs, &i->base)))
3376 0 : goto cleanup;
3377 : }
3378 6838 : if (ot->keys)
3379 8666 : for (n = ol_first_node(ot->keys); n; n = n->next) {
3380 1828 : sql_key *k = NULL;
3381 :
3382 1828 : if ((res = key_dup(tr, n->data, t, &k)) || (res = ol_add(t->keys, &k->base)))
3383 0 : goto cleanup;
3384 : }
3385 6838 : if (ot->triggers)
3386 6966 : for (n = ol_first_node(ot->triggers); n; n = n->next) {
3387 128 : sql_trigger *tri = NULL;
3388 :
3389 128 : if ((res = trigger_dup(tr, n->data, t, &tri)) || (res = ol_add(t->triggers, &tri->base)))
3390 0 : goto cleanup;
3391 : }
3392 6838 : if (ot->members)
3393 1082 : for (n = ot->members->h; n; n = n->next) {
3394 504 : sql_part *pt = NULL;
3395 :
3396 504 : if ((res = part_dup(tr, n->data, t, &pt)))
3397 0 : goto cleanup;
3398 504 : list_append(t->members, pt);
3399 : }
3400 6838 : if (isTable(t)) {
3401 6252 : if (isTempTable(t)) {
3402 4644 : if ((res = store->storage_api.create_del(tr, t)))
3403 0 : goto cleanup;
3404 : } else {
3405 1608 : ATOMIC_PTR_SET(&t->data, store->storage_api.del_dup(ot));
3406 : }
3407 : }
3408 6838 : if ((res = os_add(isLocalTemp(t) ? tr->localtmps : t->s->tables, tr, t->base.name, &t->base)))
3409 10 : goto cleanup;
3410 :
3411 6828 : cleanup:
3412 10 : if (res) {
3413 : t = NULL;
3414 : }
3415 6838 : *tres = t;
3416 6838 : return res;
3417 : }
3418 :
3419 : sql_table *
3420 4618 : globaltmp_instantiate(sql_trans *tr, sql_table *ot)
3421 : {
3422 4618 : assert(isGlobal(ot)&& isTempTable(ot));
3423 4618 : sql_table *t = NULL;
3424 4618 : if (table_dup(tr, ot, NULL, NULL, &t, false) == LOG_OK)
3425 4618 : return t;
3426 : return NULL;
3427 : }
3428 :
3429 : static int
3430 282098 : new_table(sql_trans *tr, sql_table *t, sql_table **tres)
3431 : {
3432 282098 : int res = LOG_OK;
3433 282098 : if (!isGlobalTemp(t))
3434 281966 : t = find_sql_table(tr, t->s, t->base.name); /* could have changed by depending changes */
3435 :
3436 282098 : if (!isLocalTemp(t) && !isNew(t) && !os_obj_intransaction(t->s->tables, tr, &t->base))
3437 2178 : res = table_dup(tr, t, t->s, NULL, tres, true);
3438 : else
3439 279920 : *tres = t;
3440 282098 : return res;
3441 : }
3442 :
3443 : static sql_arg *
3444 358378 : arg_dup(sql_trans *tr, sql_schema *s, sql_arg *oa)
3445 : {
3446 358378 : sql_arg *a = ZNEW(sql_arg);
3447 :
3448 358378 : if (a) {
3449 358378 : a->name =_STRDUP(oa->name);
3450 358378 : a->inout = oa->inout;
3451 358378 : dup_sql_type(tr, s, &(oa->type), &(a->type));
3452 : }
3453 358378 : return a;
3454 : }
3455 :
3456 : static int
3457 13 : func_dup(sql_trans *tr, sql_func *of, sql_schema *s)
3458 : {
3459 13 : sql_func *f = ZNEW(sql_func);
3460 :
3461 : /* 'func_dup' is aimed at FUNC_LANG_SQL functions ONLY, so f->imp and f->instantiated won't be set */
3462 13 : base_init(NULL, &f->base, of->base.id, 0, of->base.name);
3463 13 : f->mod =_STRDUP(of->mod);
3464 13 : f->type = of->type;
3465 13 : f->lang = of->lang;
3466 13 : f->semantics = of->semantics;
3467 13 : f->side_effect = of->side_effect;
3468 13 : f->varres = of->varres;
3469 13 : f->vararg = of->vararg;
3470 13 : f->fix_scale = of->fix_scale;
3471 13 : f->system = of->system;
3472 13 : f->private = of->private;
3473 13 : f->order_required = of->order_required;
3474 13 : f->opt_order = of->opt_order;
3475 13 : f->query = (of->query)?_STRDUP(of->query):NULL;
3476 13 : f->s = s;
3477 13 : f->sa = NULL;
3478 :
3479 13 : f->ops = list_create((fdestroy) &arg_destroy);
3480 30 : for (node *n=of->ops->h; n; n = n->next)
3481 17 : list_append(f->ops, arg_dup(tr, s, n->data));
3482 13 : if (of->res) {
3483 11 : f->res = list_create((fdestroy) &arg_destroy);
3484 22 : for (node *n=of->res->h; n; n = n->next)
3485 11 : list_append(f->res, arg_dup(tr, s, n->data));
3486 : }
3487 :
3488 13 : return os_add(s->funcs, tr, f->base.name, &f->base);
3489 : }
3490 :
3491 : static int
3492 20681 : store_reset_sql_functions(sql_trans *tr, sqlid id)
3493 : {
3494 20681 : sqlstore *store = tr->store;
3495 20681 : int res = LOG_OK, sql_lang = (int) FUNC_LANG_SQL; /* functions other than SQL don't require to be instantiated again */
3496 20681 : sql_schema *syss = find_sql_schema(tr, "sys");
3497 20681 : sql_table *deps = find_sql_table(tr, syss, "dependencies");
3498 20681 : rids *sql_funcs = NULL, *depends = NULL, *joined = NULL;
3499 :
3500 : /* Find dependencies from the object */
3501 20681 : depends = store->table_api.rids_select(tr, find_sql_column(deps, "id"), &id, &id, NULL);
3502 20681 : if (depends == NULL)
3503 : return -1;
3504 20681 : if (store->table_api.rids_empty(depends)) { /* nothing depends on the object, return */
3505 19876 : store->table_api.rids_destroy(depends);
3506 19876 : return res;
3507 : }
3508 : /* Get SQL functions */
3509 805 : sql_table *funcs = find_sql_table(tr, syss, "functions");
3510 805 : sql_column *func_id = find_sql_column(funcs, "id");
3511 805 : if (!(sql_funcs = store->table_api.rids_select(tr, find_sql_column(funcs, "language"), &sql_lang, &sql_lang, NULL))) {
3512 0 : store->table_api.rids_destroy(depends);
3513 0 : return -1;
3514 : }
3515 : /* Do the semijoin */
3516 805 : joined = store->table_api.rids_semijoin(tr, sql_funcs, func_id, depends, find_sql_column(deps, "depend_id"));
3517 805 : store->table_api.rids_destroy(depends);
3518 805 : if (!joined) {
3519 0 : store->table_api.rids_destroy(sql_funcs);
3520 0 : return -1;
3521 : }
3522 :
3523 1162 : for (oid rid = store->table_api.rids_next(joined); !is_oid_nil(rid); rid = store->table_api.rids_next(joined)) {
3524 357 : sqlid fid = store->table_api.column_find_sqlid(tr, func_id, rid);
3525 357 : sql_func *f = sql_trans_find_func(tr, fid); /* could have changed by depending changes */
3526 : /* if it is on the same transaction, then don't dup it again */
3527 357 : if (isNew(f) || os_obj_intransaction(f->s->funcs, tr, &f->base)) {
3528 344 : if (f->instantiated) {
3529 : /* clean backend code */
3530 0 : backend_freecode(sql_shared_module_name, 0, f->imp);
3531 0 : f->instantiated = FALSE;
3532 0 : _DELETE(f->imp);
3533 : }
3534 13 : } else if ((res = func_dup(tr, f, f->s))) {
3535 0 : store->table_api.rids_destroy(joined);
3536 0 : return res;
3537 : }
3538 : }
3539 805 : store->table_api.rids_destroy(joined);
3540 805 : return res;
3541 : }
3542 :
3543 : int
3544 6969 : sql_trans_copy_key( sql_trans *tr, sql_table *t, sql_key *k, sql_key **kres)
3545 : {
3546 6969 : sqlstore *store = tr->store;
3547 7006 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
3548 6969 : sql_table *syskey = find_sql_table(tr, syss, "keys");
3549 6969 : sql_table *syskc = find_sql_table(tr, syss, "objects");
3550 6969 : int neg = -1, action = -1, nr, res = LOG_OK;
3551 6969 : node *n;
3552 6969 : sql_key *nk;
3553 6969 : sql_table *dup = NULL;
3554 :
3555 6969 : if ((res = new_table(tr, t, &dup)))
3556 : return res;
3557 6969 : t = dup;
3558 6969 : if ((res = key_dup(tr, k, t, &nk)))
3559 : return res;
3560 6969 : sql_fkey *fk = (sql_fkey*)nk;
3561 6969 : if ((res = ol_add(t->keys, &nk->base)))
3562 : return res;
3563 :
3564 6969 : if (nk->type == fkey)
3565 925 : action = (fk->on_update<<8) + fk->on_delete;
3566 :
3567 6969 : char *strnil = (char*)ATOMnilptr(TYPE_str);
3568 6969 : if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action
3569 : , (nk->type == ckey)? &nk->check : &strnil )))
3570 : return res;
3571 :
3572 6969 : if (nk->type == fkey) {
3573 925 : sql_key *rkey = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
3574 925 : if (!rkey)
3575 : return LOG_ERR;
3576 :
3577 924 : if ((res = sql_trans_create_dependency(tr, rkey->base.id, nk->base.id, FKEY_DEPENDENCY)))
3578 : return res;
3579 : /* TODO this has to be cleaned out once the sql_cat.c cleanup is done */
3580 924 : if (!isNew(rkey) && (res = sql_trans_add_dependency(tr, rkey->base.id, ddl)))
3581 : return res;
3582 924 : if (!isNew(rkey) && (res = sql_trans_add_dependency(tr, rkey->t->base.id, ddl))) /* this dependency is needed for merge tables */
3583 : return res;
3584 924 : if (!isNew(rkey) && isGlobal(rkey->t) && !isGlobalTemp(rkey->t) && (res = sql_trans_add_dependency(tr, rkey->t->base.id, dml))) /* disallow concurrent updates on other key */
3585 : return res;
3586 924 : if ((res = store_reset_sql_functions(tr, rkey->t->base.id))) /* reset sql functions depending on the table */
3587 : return res;
3588 : }
3589 :
3590 14580 : for (n = nk->columns->h, nr = 0; n; n = n->next, nr++) {
3591 7612 : sql_kc *kc = n->data;
3592 :
3593 7612 : if ((res = store->table_api.table_insert(tr, syskc, &nk->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))))
3594 0 : return res;
3595 :
3596 7612 : if (nk->type == fkey) {
3597 956 : if ((res = sql_trans_create_dependency(tr, kc->c->base.id, nk->base.id, FKEY_DEPENDENCY)))
3598 0 : return res;
3599 6656 : } else if (nk->type == ukey || nk->type == ckey) {
3600 2395 : if ((res = sql_trans_create_dependency(tr, kc->c->base.id, nk->base.id, KEY_DEPENDENCY)))
3601 0 : return res;
3602 4261 : } else if (nk->type == pkey) {
3603 4233 : if ((res = sql_trans_create_dependency(tr, kc->c->base.id, nk->base.id, KEY_DEPENDENCY)))
3604 0 : return res;
3605 4233 : if ((res = sql_trans_alter_null(tr, kc->c, 0)))
3606 0 : return res;
3607 : }
3608 :
3609 : /* TODO this has to be cleaned out too */
3610 7612 : if (!isNew(kc->c) && (res = sql_trans_add_dependency(tr, kc->c->base.id, ddl)))
3611 0 : return res;
3612 : }
3613 6968 : if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
3614 : return res;
3615 :
3616 : /* TODO this has to be cleaned out too */
3617 6968 : if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl))) /* this dependency is needed for merge tables */
3618 : return res;
3619 6968 : if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml))) /* disallow concurrent updates on t */
3620 : return res;
3621 6968 : if (kres)
3622 0 : *kres = nk;
3623 : return res;
3624 : }
3625 :
3626 : int
3627 7266 : sql_trans_copy_idx( sql_trans *tr, sql_table *t, sql_idx *i, sql_idx **ires)
3628 : {
3629 7266 : sqlstore *store = tr->store;
3630 7316 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
3631 7266 : sql_table *sysidx = find_sql_table(tr, syss, "idxs");
3632 7266 : sql_table *sysic = find_sql_table(tr, syss, "objects");
3633 7266 : node *n;
3634 7266 : int nr, res = LOG_OK, ncols = list_length(i->columns);
3635 7266 : sql_table *dup = NULL;
3636 :
3637 7266 : if ((res = new_table(tr, t, &dup)))
3638 : return res;
3639 7263 : t = dup;
3640 7263 : sql_idx *ni = ZNEW(sql_idx);
3641 7263 : base_init(NULL, &ni->base, i->base.id?i->base.id:next_oid(tr->store), true, i->base.name);
3642 7263 : ni->columns = list_create((fdestroy) &kc_destroy);
3643 7263 : ni->t = t;
3644 7263 : ni->type = i->type;
3645 7263 : ni->key = NULL;
3646 7263 : ATOMIC_PTR_INIT(&ni->data, NULL);
3647 :
3648 15263 : for (n = i->columns->h, nr = 0; n; n = n->next, nr++) {
3649 8000 : sql_kc *okc = n->data, *ic;
3650 :
3651 8000 : list_append(ni->columns, ic = kc_dup(okc, t));
3652 8000 : if (i->key && hash_index(i->type))
3653 6627 : ic->c->unique = (ncols == 1) ? 2 : MAX(ic->c->unique, 1);
3654 8000 : if ((res = store->table_api.table_insert(tr, sysic, &ni->base.id, &ic->c->base.name, &nr, ATOMnilptr(TYPE_int)))) {
3655 0 : idx_destroy(store, ni);
3656 0 : return res;
3657 : }
3658 8000 : if ((res = sql_trans_create_dependency(tr, ic->c->base.id, ni->base.id, INDEX_DEPENDENCY))) {
3659 0 : idx_destroy(store, ni);
3660 0 : return res;
3661 : }
3662 : }
3663 7263 : if ((res = ol_add(t->idxs, &ni->base)))
3664 : return res;
3665 :
3666 7263 : if (isGlobal(t) && (res = os_add(t->s->idxs, tr, ni->base.name, dup_base(&ni->base))))
3667 : return res;
3668 7263 : if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
3669 : return res;
3670 :
3671 : /* this dependency is needed for merge tables */
3672 7263 : if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl)))
3673 : return res;
3674 7263 : if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml)))
3675 : return res;
3676 :
3677 7263 : if (isDeclaredTable(i->t))
3678 7263 : if (!isDeclaredTable(t) && isTable(ni->t) && idx_has_column(ni->type))
3679 7061 : if ((res = store->storage_api.create_idx(tr, ni))) {
3680 : return res;
3681 : }
3682 7263 : if (!isDeclaredTable(t))
3683 7263 : if ((res = store->table_api.table_insert(tr, sysidx, &ni->base.id, &t->base.id, &ni->type, &ni->base.name))) {
3684 : return res;
3685 : }
3686 :
3687 7263 : if (ires)
3688 0 : *ires = ni;
3689 : return res;
3690 : }
3691 :
3692 : int
3693 0 : sql_trans_copy_trigger( sql_trans *tr, sql_table *t, sql_trigger *tri, sql_trigger **tres)
3694 : {
3695 0 : sqlstore *store = tr->store;
3696 0 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
3697 0 : sql_table *systr = find_sql_table(tr, syss, "triggers");
3698 0 : sql_table *sysic = find_sql_table(tr, syss, "objects");
3699 0 : node *n;
3700 0 : int nr, res = LOG_OK;
3701 0 : sql_trigger *nt = ZNEW(sql_trigger);
3702 0 : char *strnil = (char*)ATOMnilptr(TYPE_str);
3703 :
3704 0 : base_init(NULL, &nt->base, tri->base.id?tri->base.id:next_oid(tr->store), true, tri->base.name);
3705 0 : nt->columns = list_create((fdestroy) &kc_destroy);
3706 0 : nt->t = t;
3707 0 : nt->time = tri->time;
3708 0 : nt->orientation = tri->orientation;
3709 0 : nt->event = tri->event;
3710 0 : nt->old_name = nt->new_name = nt->condition = NULL;
3711 0 : if (tri->old_name)
3712 0 : nt->old_name =_STRDUP(tri->old_name);
3713 0 : if (tri->new_name)
3714 0 : nt->new_name =_STRDUP(tri->new_name);
3715 0 : if (tri->condition)
3716 0 : nt->condition =_STRDUP(tri->condition);
3717 0 : nt->statement =_STRDUP(tri->statement);
3718 :
3719 0 : for (n = tri->columns->h, nr = 0; n; n = n->next, nr++) {
3720 0 : sql_kc *okc = n->data, *ic;
3721 :
3722 0 : list_append(nt->columns, ic = kc_dup(okc, t));
3723 0 : if ((res = store->table_api.table_insert(tr, sysic, &nt->base.id, &ic->c->base.name, &nr, ATOMnilptr(TYPE_int)))) {
3724 0 : trigger_destroy(store, nt);
3725 0 : return res;
3726 : }
3727 0 : if ((res = sql_trans_create_dependency(tr, ic->c->base.id, nt->base.id, TRIGGER_DEPENDENCY))) {
3728 0 : trigger_destroy(store, nt);
3729 0 : return res;
3730 : }
3731 : }
3732 0 : if ((res = ol_add(t->triggers, &nt->base)))
3733 : return res;
3734 :
3735 0 : assert(isGlobal(t));
3736 0 : if ((res = os_add(t->s->triggers, tr, nt->base.name, dup_base(&nt->base))))
3737 : return res;
3738 0 : if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
3739 : return res;
3740 :
3741 0 : if (!isDeclaredTable(t))
3742 0 : if ((res = store->table_api.table_insert(tr, systr, &nt->base.id, &nt->base.name, &t->base.id, &nt->time, &nt->orientation,
3743 0 : &nt->event, (nt->old_name)?&nt->old_name:&strnil, (nt->new_name)?&nt->new_name:&strnil,
3744 0 : (nt->condition)?&nt->condition:&strnil, &nt->statement))) {
3745 : return res;
3746 : }
3747 :
3748 0 : if (tres)
3749 0 : *tres = nt;
3750 : return res;
3751 : }
3752 :
3753 : static int
3754 272809 : type_digits(sql_subtype *type)
3755 : {
3756 272809 : int digits = type->digits;
3757 :
3758 272809 : if (digits && type->type->eclass == EC_NUM) {
3759 111019 : if(type->type->localtype == TYPE_bte) {
3760 : digits = 7;
3761 : } else if(type->type->localtype == TYPE_sht) {
3762 : digits = 15;
3763 : } else if(type->type->localtype == TYPE_int) {
3764 : digits = 31;
3765 : } else if(type->type->localtype == TYPE_lng) {
3766 : digits = 63;
3767 : #ifdef HAVE_HGE
3768 : } else if(type->type->localtype == TYPE_hge) {
3769 272809 : digits = 127;
3770 : #endif
3771 : }
3772 : }
3773 272809 : return digits;
3774 : }
3775 :
3776 : static sql_column *
3777 273257 : create_sql_column_with_id(allocator *sa, sqlid id, sql_table *t, const char *name, sql_subtype *tpe, bte column_type)
3778 : {
3779 273257 : sql_column *col = SA_ZNEW(sa, sql_column);
3780 :
3781 273257 : base_init(sa, &col->base, id, true, name);
3782 273257 : col->type = *tpe;
3783 273257 : col->def = NULL;
3784 273257 : col->null = 1;
3785 273257 : col->colnr = table_next_column_nr(t);
3786 273257 : col->t = t;
3787 273257 : col->unique = 0;
3788 273257 : col->storage_type = NULL;
3789 273257 : col->column_type = column_type;
3790 :
3791 273257 : if (ol_add(t->columns, &col->base))
3792 : return NULL;
3793 273257 : ATOMIC_PTR_INIT(&col->data, NULL);
3794 273257 : return col;
3795 : }
3796 :
3797 : static int
3798 10359 : sql_trans_create_column_intern(sql_column **rcol, sql_trans *tr, sql_table *t, const char *name, sql_subtype *tpe, bte column_type)
3799 : {
3800 10359 : bool needs_data = true;
3801 10359 : sqlstore *store = tr->store;
3802 10359 : sql_column *col;
3803 10371 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
3804 10359 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
3805 10359 : int res = LOG_OK;
3806 :
3807 10359 : if (!tpe)
3808 : return -1; /* TODO not sure what to do here */
3809 :
3810 10359 : col = create_sql_column_with_id(NULL, next_oid(tr->store), t, name, tpe, column_type);
3811 10359 : if (col->type.multiset)
3812 16 : t->multiset=true;
3813 10359 : if (col->type.type->composite)
3814 24 : t->composite=true;
3815 :
3816 10359 : if (tpe->type->composite || tpe->multiset) {
3817 28 : needs_data = false;
3818 28 : sql_table *tt = t;
3819 28 : if (tpe->multiset) {
3820 16 : char buf[16];
3821 16 : snprintf(buf, 16, "%%ms_%d", col->base.id);
3822 16 : col->storage_type = _STRDUP(buf);
3823 16 : if ((res = sql_trans_create_table(&tt, tr, t->s, col->storage_type, NULL, tt_table, true, t->persistence, t->commit_action, 0, 0)) != LOG_OK)
3824 0 : return res;
3825 16 : if (sql_trans_create_sequence(tr, t->s, col->storage_type, 1, 1, GDK_lng_max, 1, 1, false, true) != LOG_OK)
3826 : return res;
3827 : }
3828 28 : if (tpe->type->composite) {
3829 : /* All nested types, need the internal columns for the field contents */
3830 66 : for (node *n = col->type.type->d.fields->h; n; n = n->next) {
3831 42 : sql_arg *f = n->data;
3832 42 : sql_column *ic = NULL;
3833 42 : if (sql_trans_create_column_intern( &ic, tr, tt, f->name, &f->type, column_intern) < 0)
3834 0 : return -2;
3835 : }
3836 : } else {
3837 4 : sql_column *ic = NULL;
3838 4 : sql_subtype lt = *tpe;
3839 4 : lt.multiset = MS_VALUE;
3840 4 : if (sql_trans_create_column_intern( &ic, tr, tt, MSEL_NAME, <, column_intern) < 0)
3841 0 : return -2;
3842 : }
3843 28 : if (tpe->multiset == MS_SETOF || tpe->multiset == MS_ARRAY) { /* sets and arrays need oid col */
3844 16 : char *name = MSID_NAME;
3845 16 : sql_subtype tp = *sql_bind_localtype("int");
3846 16 : sql_column *ic = NULL;
3847 16 : if (sql_trans_create_column_intern( &ic, tr, tt, name, &tp, column_intern) < 0)
3848 0 : return -2;
3849 16 : needs_data = true; /* column its self is reference id */
3850 : }
3851 28 : if (tpe->multiset == MS_ARRAY) { /* array need order */
3852 16 : char *name = MSNR_NAME;
3853 16 : sql_subtype tp = *sql_bind_localtype("int");
3854 16 : sql_column *ic = NULL;
3855 16 : if (sql_trans_create_column_intern( &ic, tr, tt, name, &tp, column_intern) < 0)
3856 0 : return -2;
3857 : }
3858 : }
3859 :
3860 28 : if (needs_data) {
3861 10347 : if (isTable(col->t)) {
3862 5673 : if ((res = store->storage_api.create_col(tr, col))) {
3863 : return res;
3864 : }
3865 : }
3866 : }
3867 10359 : if (!isDeclaredTable(t)) {
3868 10359 : char *strnil = (char*)ATOMnilptr(TYPE_str);
3869 10359 : int digits = type_digits(&col->type);
3870 10375 : if ((res = store->table_api.table_insert(tr, syscolumn, &col->base.id, &col->base.name, &col->type.type->base.name,
3871 : &digits, &col->type.scale, &t->base.id,
3872 10359 : (col->def) ? &col->def : &strnil, &col->null, &col->colnr,
3873 10359 : (col->storage_type) ? &col->storage_type : &strnil, &col->column_type, &col->type.multiset))) {
3874 0 : return res;
3875 : }
3876 : }
3877 :
3878 10359 : if (tpe->type->s) {/* column depends on type */
3879 25 : if ((res = sql_trans_create_dependency(tr, tpe->type->base.id, col->base.id, TYPE_DEPENDENCY))) {
3880 : return res;
3881 : }
3882 25 : if (!isNew(tpe->type) && (res = sql_trans_add_dependency(tr, tpe->type->base.id, ddl))) {
3883 : return res;
3884 : }
3885 : }
3886 10359 : *rcol = col;
3887 10359 : return res;
3888 : }
3889 :
3890 : int
3891 262452 : sql_trans_copy_column( sql_trans *tr, sql_table *t, sql_column *c, sql_column **cres)
3892 : {
3893 262452 : bool needs_data = true;
3894 262452 : sqlstore *store = tr->store;
3895 262574 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
3896 262452 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
3897 262452 : sql_table *dup = NULL;
3898 262452 : int res = LOG_OK;
3899 :
3900 262452 : if ((res = new_table(tr, t, &dup)))
3901 : return res;
3902 262450 : t = dup;
3903 262450 : sql_column *col = ZNEW(sql_column);
3904 262450 : base_init(NULL, &col->base, c->base.id?c->base.id:next_oid(tr->store), true, c->base.name);
3905 262450 : dup_sql_type(tr, t->s, &(c->type), &(col->type));
3906 262450 : if (c->type.multiset)
3907 15 : t->multiset=true;
3908 262450 : if (c->type.type->composite)
3909 23 : t->composite=true;
3910 262450 : col->def = NULL;
3911 262450 : if (c->def)
3912 1401 : col->def =_STRDUP(c->def);
3913 262450 : col->null = c->null;
3914 262450 : col->colnr = table_next_column_nr(t);
3915 262450 : col->unique = c->unique;
3916 262450 : col->t = t;
3917 262450 : col->storage_type = NULL;
3918 262450 : if (c->storage_type)
3919 0 : col->storage_type =_STRDUP(c->storage_type);
3920 :
3921 262450 : if ((res = ol_add(t->columns, &col->base)))
3922 : return res;
3923 :
3924 : /* this dependency is needed for merge tables */
3925 262450 : if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl)))
3926 : return res;
3927 262450 : if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml)))
3928 : return res;
3929 :
3930 262450 : if (c->type.type->composite || c->type.multiset) {
3931 31 : needs_data = false;
3932 31 : sql_table *tt = t;
3933 31 : if (c->type.multiset) {
3934 15 : char buf[16];
3935 15 : snprintf(buf, 16, "%%ms_%d", c->base.id);
3936 15 : col->storage_type = _STRDUP(buf);
3937 15 : if ((res = sql_trans_create_table(&tt, tr, t->s, col->storage_type, NULL, tt_table, true, t->persistence, t->commit_action, 0, 0)) != LOG_OK)
3938 0 : return res;
3939 15 : if (sql_trans_create_sequence(tr, t->s, col->storage_type, 1, 1, GDK_lng_max, 1, 1, false, true) != LOG_OK)
3940 : return res;
3941 : }
3942 31 : if (c->type.type->composite) {
3943 : /* All nested types, need the internal columns for the field contents */
3944 72 : for (node *n = col->type.type->d.fields->h; n; n = n->next) {
3945 49 : sql_arg *f = n->data;
3946 49 : sql_column *ic = NULL;
3947 49 : if (sql_trans_create_column_intern( &ic, tr, tt, f->name, &f->type, column_intern) < 0)
3948 0 : return -2;
3949 : }
3950 : } else {
3951 8 : sql_column *ic = NULL;
3952 8 : sql_subtype lt = c->type;
3953 8 : lt.multiset = MS_VALUE;
3954 8 : if (sql_trans_create_column_intern( &ic, tr, tt, MSEL_NAME, <, column_intern) < 0)
3955 0 : return -2;
3956 : }
3957 31 : if (c->type.multiset == MS_SETOF || c->type.multiset == MS_ARRAY) { /* sets and arrays need oid col */
3958 15 : char *name = MSID_NAME;
3959 15 : sql_subtype tp = *sql_bind_localtype(MSID_TYPENAME);
3960 15 : sql_column *ic = NULL;
3961 15 : if (sql_trans_create_column_intern( &ic, tr, tt, name, &tp, column_intern) < 0)
3962 0 : return -2;
3963 15 : needs_data = true; /* column its self is reference id */
3964 : }
3965 31 : if (c->type.multiset == MS_ARRAY) { /* array need order */
3966 15 : char *name = MSNR_NAME;
3967 15 : sql_subtype tp = *sql_bind_localtype(MSNR_TYPENAME);
3968 15 : sql_column *ic = NULL;
3969 15 : if (sql_trans_create_column_intern( &ic, tr, tt, name, &tp, column_intern) < 0)
3970 0 : return -2;
3971 : }
3972 : }
3973 :
3974 31 : if (needs_data) {
3975 262434 : ATOMIC_PTR_INIT(&col->data, NULL);
3976 262434 : if (isDeclaredTable(c->t))
3977 262434 : if (isTable(t))
3978 52334 : if ((res = store->storage_api.create_col(tr, col))) {
3979 : return res;
3980 : }
3981 :
3982 : }
3983 262450 : if (!isDeclaredTable(t)) {
3984 262450 : char *strnil = (char*)ATOMnilptr(TYPE_str);
3985 262450 : int digits = type_digits(&col->type);
3986 262465 : if ((res = store->table_api.table_insert(tr, syscolumn, &col->base.id, &col->base.name, &col->type.type->base.name,
3987 : &digits, &col->type.scale, &t->base.id,
3988 262450 : (col->def) ? &col->def : &strnil, &col->null, &col->colnr,
3989 262450 : (col->storage_type) ? &col->storage_type : &strnil, &col->column_type, &c->type.multiset))) {
3990 0 : return res;
3991 : }
3992 262450 : if (c->type.type->s) { /* column depends on type */
3993 211 : if ((res = sql_trans_create_dependency(tr, c->type.type->base.id, col->base.id, TYPE_DEPENDENCY))) {
3994 : return res;
3995 : }
3996 211 : if (!isNew(c->type.type) && (res = sql_trans_add_dependency(tr, c->type.type->base.id, ddl))) {
3997 : return res;
3998 : }
3999 : }
4000 : }
4001 262450 : if (cres)
4002 262342 : *cres = col;
4003 : return res;
4004 : }
4005 :
4006 : static int
4007 194586 : clean_predicates_and_propagate_to_parent(sql_trans *tr)
4008 : {
4009 194586 : int res = LOG_OK;
4010 :
4011 194586 : if (!list_empty(tr->predicates)) {
4012 6047 : if (tr->parent) { /* propagate to the parent */
4013 4 : for(node *n=tr->predicates->h; n && res == LOG_OK ; n = n->next) {
4014 2 : pl *p = (pl*) n->data;
4015 2 : atom *e1 = p->r ? atom_copy(NULL, p->r) : NULL, *e2 = p->f ? atom_copy(NULL, p->f) : NULL;
4016 :
4017 2 : res = sql_trans_add_predicate(tr->parent, p->c, p->cmp, e1, e2, p->anti, p->semantics);
4018 : }
4019 : }
4020 6047 : list_destroy(tr->predicates);
4021 6047 : tr->predicates = NULL;
4022 : }
4023 194589 : if (!list_empty(tr->dependencies)) {
4024 2783 : if (tr->parent) { /* propagate to the parent */
4025 6 : for(node *n=tr->dependencies->h; n && res == LOG_OK ; n = n->next) {
4026 4 : sql_dependency_change *dp = (sql_dependency_change*)n->data;
4027 4 : res = sql_trans_add_dependency(tr->parent, dp->objid, dp->type);
4028 : }
4029 : }
4030 2783 : list_destroy(tr->dependencies);
4031 2783 : tr->dependencies = NULL;
4032 : }
4033 194586 : if (!list_empty(tr->depchanges)) {
4034 57136 : if (tr->parent) { /* propagate to the parent */
4035 6 : for(node *n=tr->depchanges->h; n && res == LOG_OK ; n = n->next) {
4036 3 : sql_dependency_change *dp = (sql_dependency_change*)n->data;
4037 3 : res = sql_trans_add_dependency_change(tr->parent, dp->objid, dp->type);
4038 : }
4039 : }
4040 57136 : list_destroy(tr->depchanges);
4041 57147 : tr->depchanges = NULL;
4042 : }
4043 194597 : return res;
4044 : }
4045 :
4046 : static void
4047 63536 : sql_trans_rollback(sql_trans *tr, bool commit_lock)
4048 : {
4049 63536 : sqlstore *store = tr->store;
4050 63536 : if (!list_empty(tr->changes)) {
4051 2189 : struct os_iter oi;
4052 2189 : os_iterator(&oi, tr->localtmps, tr, NULL);
4053 3382 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
4054 1193 : sql_table *t = (sql_table *) b;
4055 1193 : if (t->commit_action == CA_DROP && !b->deleted) {
4056 3 : (void) sql_trans_drop_table_id(tr, t->s, b->id, DROP_RESTRICT);// TODO transaction_layer_revamp: fix result code sql_trans_drop_table_id
4057 : }
4058 : }
4059 : /* revert the change list */
4060 2189 : list *nl = tr->changes;
4061 2189 : list_revert(nl);
4062 :
4063 : /* rollback */
4064 2189 : if (!commit_lock)
4065 1139 : MT_lock_set(&store->commit);
4066 2189 : store_lock(store);
4067 2189 : ulng oldest = store_oldest(store, tr);
4068 2189 : ulng commit_ts = store_get_timestamp(store); /* use most recent timestamp such that we can cleanup safely */
4069 14125 : for(node *n=nl->h; n; n = n->next) {
4070 11936 : sql_change *c = n->data;
4071 :
4072 11936 : if (!c)
4073 0 : continue;
4074 11936 : if (c->commit)
4075 11936 : c->commit(tr, c, 0 /* ie rollback */, oldest);
4076 11936 : c->ts = commit_ts;
4077 : }
4078 2189 : store_pending_changes(store, oldest, tr);
4079 14125 : for(node *n=nl->h; n; n = n->next) {
4080 11936 : sql_change *c = n->data;
4081 :
4082 11936 : if (!c)
4083 0 : continue;
4084 11936 : if (!c->cleanup) {
4085 0 : _DELETE(c);
4086 11936 : } else if (c->cleanup && !c->cleanup(store, c, oldest)) {
4087 : /* TODO change to node stealing (no allocs here) */
4088 8611 : store->changes = list_add(store->changes, c);
4089 : } else
4090 11936 : _DELETE(c);
4091 : }
4092 2189 : store_unlock(store);
4093 2189 : if (!commit_lock)
4094 1139 : MT_lock_unset(&store->commit);
4095 2189 : list_destroy(tr->changes);
4096 2189 : tr->changes = NULL;
4097 2189 : tr->logchanges = 0;
4098 : } else {
4099 61349 : if (commit_lock || MT_lock_try(&store->commit)) {
4100 44841 : store_lock(store);
4101 44841 : ulng oldest = store_oldest(store, tr);
4102 44841 : store_pending_changes(store, oldest, tr);
4103 44841 : store_unlock(store);
4104 44841 : if (!commit_lock)
4105 44841 : MT_lock_unset(&store->commit);
4106 : }
4107 : }
4108 :
4109 63539 : if (!list_empty(tr->predicates)) {
4110 1177 : list_destroy(tr->predicates);
4111 1177 : tr->predicates = NULL;
4112 : }
4113 63537 : if (!list_empty(tr->dependencies)) {
4114 181 : list_destroy(tr->dependencies);
4115 181 : tr->dependencies = NULL;
4116 : }
4117 63538 : if (!list_empty(tr->depchanges)) {
4118 1109 : list_destroy(tr->depchanges);
4119 1109 : tr->depchanges = NULL;
4120 : }
4121 63537 : }
4122 :
4123 : sql_trans *
4124 38412 : sql_trans_destroy(sql_trans *tr)
4125 : {
4126 38412 : sql_trans *res = tr->parent;
4127 :
4128 38412 : TRC_DEBUG(SQL_STORE, "Destroy transaction: %p\n", tr);
4129 38412 : _DELETE(tr->name);
4130 38412 : assert(!tr->active || tr->parent);
4131 38412 : if (!list_empty(tr->changes))
4132 19 : sql_trans_rollback(tr, false);
4133 38412 : sqlstore *store = tr->store;
4134 38412 : os_destroy(tr->localtmps, store);
4135 38412 : MT_lock_destroy(&tr->lock);
4136 38412 : if (!list_empty(tr->dropped))
4137 0 : list_destroy(tr->dropped);
4138 38412 : _DELETE(tr);
4139 38412 : return res;
4140 : }
4141 :
4142 : static sql_trans *
4143 38412 : sql_trans_create_(sqlstore *store, sql_trans *parent, const char *name)
4144 : {
4145 38412 : if (name && !parent) /* unlikely */
4146 : return NULL;
4147 :
4148 38412 : sql_trans *tr = ZNEW(sql_trans);
4149 :
4150 38412 : if (!tr)
4151 : return NULL;
4152 38412 : MT_lock_init(&tr->lock, "trans_lock");
4153 38412 : tr->parent = parent;
4154 38412 : if (name) {
4155 62 : _DELETE(parent->name);
4156 62 : parent->name = _STRDUP(name);
4157 : }
4158 :
4159 38412 : if (!parent) {
4160 38350 : tr->localtmps = os_new(NULL, (destroy_fptr) &table_destroy, true, true, false, false, store);
4161 : }
4162 : else {
4163 62 : tr->localtmps = os_dup(parent->localtmps);
4164 : }
4165 :
4166 38412 : store_lock(store);
4167 38412 : tr->store = store;
4168 38412 : tr->tid = store_transaction_id(store);
4169 38412 : tr->cat = store->cat;
4170 38412 : if (!tr->cat) {
4171 357 : store->cat = tr->cat = ZNEW(sql_catalog);
4172 357 : store->cat->schemas = os_new(NULL, (destroy_fptr) &schema_destroy, false, true, true, true, store);
4173 357 : store->cat->objects = os_new(NULL, (destroy_fptr) &key_destroy, false, false, true, false, store);
4174 357 : ATOMIC_INIT(&store->cat->schema_version, 0);
4175 : }
4176 38412 : tr->tmp = store->tmp;
4177 38412 : TRC_DEBUG(SQL_STORE, "New transaction: %p\n", tr);
4178 38412 : store_unlock(store);
4179 38412 : return tr;
4180 : }
4181 :
4182 : static int
4183 40 : schema_dup(sql_trans *tr, sql_schema *s, const char *name, sql_schema **rs)
4184 : {
4185 40 : sql_schema *ns = ZNEW(sql_schema);
4186 40 : int res = LOG_OK;
4187 :
4188 40 : base_init(NULL, &ns->base, s->base.id, 0, name);
4189 40 : ns->auth_id = s->auth_id;
4190 40 : ns->owner = s->owner;
4191 40 : ns->system = s->system;
4192 :
4193 40 : sqlstore *store = tr->store;
4194 40 : assert(!isTempSchema(s)); // TODO transaction_layer_revamp: check if this is really true
4195 40 : ns->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
4196 40 : ns->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
4197 40 : ns->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
4198 40 : ns->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
4199 40 : ns->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
4200 40 : ns->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
4201 :
4202 : /* table_dup will dup keys, idxs, triggers and parts */
4203 40 : struct os_iter oi;
4204 40 : os_iterator(&oi, s->tables, tr, NULL);
4205 41 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
4206 1 : sql_table *t = NULL;
4207 1 : if ((res = table_dup(tr, (sql_table*)b, ns, NULL, &t, true))) {
4208 0 : schema_destroy(tr->store, ns);
4209 0 : return res;
4210 : }
4211 : }
4212 :
4213 : /* we can share the funcs and types */
4214 40 : ns->funcs = os_dup(s->funcs);
4215 40 : ns->types = os_dup(s->types);
4216 40 : ns->store = s->store;
4217 40 : ns->internal = NULL;
4218 40 : *rs = ns;
4219 40 : return res;
4220 : }
4221 :
4222 : sql_trans *
4223 419 : sql_trans_create(sqlstore *store, sql_trans *parent, const char *name)
4224 : {
4225 419 : sql_trans *tr = sql_trans_create_(store, parent, name);
4226 419 : if (tr) {
4227 419 : tr->ts = store_timestamp(store);
4228 419 : tr->active = 1;
4229 : }
4230 419 : return tr;
4231 : }
4232 :
4233 : static int
4234 6989 : sql_trans_valid(sql_trans *tr)
4235 : {
4236 6989 : int ok = LOG_OK;
4237 6989 : sqlstore *store = tr->store;
4238 :
4239 6989 : if (!list_empty(tr->predicates)) {
4240 : /* for each predicate check if that table/column has changes */
4241 26491 : for(node *n = tr->predicates->h; n; n = n->next) {
4242 20506 : pl *p = n->data;
4243 20506 : sql_column *c = p->c;
4244 :
4245 20506 : if (c->t && isTable(c->t) && !isNew(c) && !isTempTable(c->t)) {
4246 20504 : if ((ok = store->storage_api.tab_validate(tr, c->t, 0)))
4247 : break;
4248 : }
4249 : }
4250 : }
4251 6989 : return ok;
4252 : }
4253 :
4254 : static inline int
4255 68456 : transaction_add_hash_entry(sql_hash *h, sqlid id, sql_dependency_change_type tpe, ulng ts)
4256 : {
4257 68456 : sql_dependency_change *next_change = MNEW(sql_dependency_change);
4258 :
4259 68456 : if (!next_change)
4260 : return LOG_ERR;
4261 68456 : *next_change = (sql_dependency_change) {
4262 : .objid = id,
4263 : .type = tpe,
4264 : .ts = ts
4265 : };
4266 :
4267 68456 : int key = h->key(next_change);
4268 68456 : sql_hash_e *he = h->buckets[key&(h->size-1)];
4269 :
4270 162948 : for (; he ; he = he->chain) { /* find if the entry is already present */
4271 120035 : sql_dependency_change *schange = (sql_dependency_change*) he->value;
4272 :
4273 120035 : if (schange->objid == id && schange->ts == ts && schange->type == tpe) {
4274 25543 : _DELETE(next_change);
4275 25543 : return LOG_OK;
4276 : }
4277 : }
4278 :
4279 42913 : if (!hash_add(h, key, next_change)) {
4280 0 : _DELETE(next_change);
4281 0 : return LOG_ERR;
4282 : }
4283 : return LOG_OK;
4284 : }
4285 :
4286 : static int
4287 59173 : transaction_check_dependencies_and_removals(sql_trans *tr)
4288 : {
4289 59173 : int ok = LOG_OK;
4290 59173 : sqlstore *store = tr->store;
4291 :
4292 : /* test dependencies and removals crossed for conflicts */
4293 59173 : if (!list_empty(tr->dependencies) && !hash_empty(store->depchanges)) {
4294 50 : for (node *n = tr->dependencies->h; n && ok == LOG_OK; n = n->next) {
4295 30 : sql_dependency_change *lchange = (sql_dependency_change*) n->data;
4296 30 : int key = store->depchanges->key(lchange);
4297 30 : sql_hash_e *he = store->depchanges->buckets[key&(store->depchanges->size-1)];
4298 :
4299 52 : for (; he && ok == LOG_OK; he = he->chain) {
4300 22 : sql_dependency_change *schange = (sql_dependency_change*) he->value;
4301 :
4302 : /* conflict only if transactions overlap */
4303 22 : if (schange->ts >= tr->ts && lchange->objid == schange->objid && lchange->type == schange->type)
4304 22 : ok = LOG_CONFLICT;
4305 : }
4306 : }
4307 : }
4308 59173 : if (ok == LOG_OK && !list_empty(tr->depchanges) && !hash_empty(store->dependencies)) {
4309 83 : for (node *n = tr->depchanges->h; n && ok == LOG_OK; n = n->next) {
4310 48 : sql_dependency_change *lchange = (sql_dependency_change*) n->data;
4311 48 : int key = store->dependencies->key(lchange);
4312 48 : sql_hash_e *he = store->dependencies->buckets[key&(store->dependencies->size-1)];
4313 :
4314 86 : for (; he && ok == LOG_OK; he = he->chain) {
4315 38 : sql_dependency_change *schange = (sql_dependency_change*) he->value;
4316 :
4317 : /* conflict only if transactions overlap */
4318 38 : if (schange->ts >= tr->ts && lchange->objid == schange->objid && lchange->type == schange->type)
4319 38 : ok = LOG_CONFLICT;
4320 : }
4321 : }
4322 : }
4323 59173 : return ok;
4324 : }
4325 :
4326 : int
4327 195607 : sql_trans_commit(sql_trans *tr)
4328 : {
4329 195607 : int ok = LOG_OK;
4330 195607 : sqlstore *store = tr->store;
4331 :
4332 195607 : if (!list_empty(tr->changes)) {
4333 67144 : struct os_iter oi;
4334 67144 : os_iterator(&oi, tr->localtmps, tr, NULL);
4335 89652 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
4336 22531 : sql_table *t = (sql_table *) b;
4337 22531 : if (t->commit_action == CA_DROP && !b->deleted) {
4338 22531 : (void) sql_trans_drop_table_id(tr, t->s, b->id, DROP_RESTRICT);;// TODO transaction_layer_revamp: fix result code sql_trans_drop_table_id
4339 : }
4340 : }
4341 :
4342 67106 : bool flush = false;
4343 67106 : ulng commit_ts = 0, oldest = 0, log_file_id = 0;
4344 :
4345 67106 : MT_lock_set(&store->commit);
4346 :
4347 67170 : if (!tr->parent && !list_empty(tr->predicates)) {
4348 6989 : ok = sql_trans_valid(tr);
4349 6989 : if (ok != LOG_OK) {
4350 1004 : sql_trans_rollback(tr, true);
4351 1004 : MT_lock_unset(&store->commit);
4352 2054 : return ok == LOG_CONFLICT ? SQL_CONFLICT : SQL_ERR;
4353 : }
4354 : }
4355 :
4356 132315 : if (!tr->parent &&
4357 129493 : (!list_empty(tr->dependencies) || !list_empty(tr->depchanges))) {
4358 59173 : ok = transaction_check_dependencies_and_removals(tr);
4359 59173 : if (ok != LOG_OK) {
4360 46 : sql_trans_rollback(tr, true);
4361 46 : MT_lock_unset(&store->commit);
4362 46 : return ok == LOG_CONFLICT ? SQL_CONFLICT : SQL_ERR;
4363 : }
4364 : }
4365 :
4366 : /* log changes should only be done if there is something to log */
4367 66120 : const bool log = !tr->parent && tr->logchanges > 0;
4368 :
4369 63095 : if (log) {
4370 63095 : const lng min_changes = ATOMIC_GET(&GDKdebug) & TESTINGMASK ? 5 : 1000000;
4371 63095 : flush = (tr->logchanges > min_changes && list_empty(store->changes));
4372 : }
4373 :
4374 5788 : if (flush)
4375 5788 : MT_lock_set(&store->flush);
4376 66120 : if (log) {
4377 63095 : ok = store->logger_api.log_tstart(store, flush, &log_file_id); /* wal start */
4378 : /* log */
4379 532616 : for(node *n=tr->changes->h; n && ok == LOG_OK; n = n->next) {
4380 469521 : sql_change *c = n->data;
4381 :
4382 469521 : if (c->log && ok == LOG_OK)
4383 257320 : ok = c->log(tr, c);
4384 : }
4385 63095 : if (ok == LOG_OK && !list_empty(store->seqchanges)) {
4386 670 : sequences_lock(store);
4387 1483 : for(node *n = store->seqchanges->h; n; ) {
4388 813 : node *next = n->next;
4389 813 : log_store_sequence(store, n->data);
4390 813 : list_remove_node(store->seqchanges, NULL, n);
4391 813 : n = next;
4392 : }
4393 670 : sequences_unlock(store);
4394 : }
4395 63095 : if (ok == LOG_OK && store->prev_oid != (sqlid) ATOMIC_GET(&store->obj_id)) {
4396 6276 : if (!flush)
4397 2127 : MT_lock_set(&store->flush);
4398 6276 : ok = store->logger_api.log_tsequence(store, OBJ_SID, store->obj_id);
4399 6276 : if (!flush)
4400 2127 : MT_lock_unset(&store->flush);
4401 : }
4402 63095 : store->prev_oid = (sqlid) ATOMIC_GET(&store->obj_id);
4403 :
4404 :
4405 63095 : if (ok == LOG_OK)
4406 63095 : ok = store->logger_api.log_tend(store); /* wal end */
4407 : }
4408 66120 : store_lock(store);
4409 :
4410 66120 : if (tr->parent) {
4411 17 : commit_ts = oldest = tr->parent->tid;
4412 17 : tr->parent->logchanges += tr->logchanges;
4413 : } else {
4414 66103 : commit_ts = store_timestamp(store);
4415 66103 : oldest = store_oldest(store, tr);
4416 : }
4417 66120 : tr->logchanges = 0;
4418 66120 : TRC_DEBUG(SQL_STORE, "Forwarding changes (" ULLFMT ", " ULLFMT ") -> " ULLFMT "\n", tr->tid, tr->ts, commit_ts);
4419 : /* apply committed changes */
4420 66120 : if (ATOMIC_GET(&store->nr_active) == 1 && !tr->parent)
4421 66120 : oldest = commit_ts;
4422 66120 : store_pending_changes(store, oldest, tr);
4423 636406 : for(node *n=tr->changes->h; n && ok == LOG_OK; n = n->next) {
4424 570286 : sql_change *c = n->data;
4425 :
4426 570286 : if (c->commit && ok == LOG_OK)
4427 570286 : ok = c->commit(tr, c, commit_ts, oldest);
4428 : else
4429 0 : c->obj->new = 0;
4430 570286 : c->ts = commit_ts;
4431 : }
4432 : /* propagate transaction dependencies to the storage only if other transactions are running */
4433 66120 : if (ok == LOG_OK && !tr->parent && ATOMIC_GET(&store->nr_active) > 1) {
4434 42810 : if (!list_empty(tr->dependencies)) {
4435 241 : for (node *n = tr->dependencies->h; n && ok == LOG_OK; n = n->next) {
4436 183 : sql_dependency_change *lchange = (sql_dependency_change*) n->data;
4437 183 : ok = transaction_add_hash_entry(store->dependencies, lchange->objid, lchange->type, commit_ts);
4438 : }
4439 : }
4440 42810 : if (!list_empty(tr->depchanges)) {
4441 111018 : for (node *n = tr->depchanges->h; n && ok == LOG_OK; n = n->next) {
4442 68273 : sql_dependency_change *lchange = (sql_dependency_change*) n->data;
4443 68273 : ok = transaction_add_hash_entry(store->depchanges, lchange->objid, lchange->type, commit_ts);
4444 : }
4445 : }
4446 : }
4447 : /* garbage collect */
4448 636406 : for(node *n=tr->changes->h; n && ok == LOG_OK; ) {
4449 570286 : node *next = n->next;
4450 570286 : sql_change *c = n->data;
4451 :
4452 570286 : n->data = NULL;
4453 570286 : if (c) {
4454 570286 : if (!c->cleanup || c->cleanup(store, c, oldest)) {
4455 395132 : _DELETE(c);
4456 175154 : } else if (tr->parent) { /* need to keep everything */
4457 37 : tr->parent->changes = list_add(tr->parent->changes, c);
4458 : } else {
4459 175117 : store->changes = list_add(store->changes, c);
4460 : }
4461 : }
4462 : n = next;
4463 : }
4464 66120 : tr->active = 2; /* small hack enabling to signal that this transaction has committed */
4465 66120 : tr->ts = commit_ts; /* fix profiler output */
4466 66120 : store_unlock(store);
4467 : /* flush the log structure */
4468 66120 : if (log) {
4469 63095 : if (!flush)
4470 57307 : MT_lock_unset(&store->commit); /* release the commit log when flushing to disk */
4471 63095 : if (ok == LOG_OK)
4472 63095 : ok = store->logger_api.log_tflush(store, log_file_id, commit_ts); /* flush/sync */
4473 63095 : if (!flush)
4474 57307 : MT_lock_set(&store->commit); /* release the commit log when flushing to disk */
4475 57307 : if (flush)
4476 5788 : MT_lock_unset(&store->flush);
4477 : }
4478 66120 : MT_lock_unset(&store->commit);
4479 66113 : if (ok == LOG_OK) {
4480 66113 : list_destroy(tr->changes);
4481 66113 : tr->changes = NULL;
4482 : }
4483 128482 : } else if (ATOMIC_GET(&store->nr_active) == 1) { /* just me cleanup */
4484 48086 : MT_lock_set(&store->commit);
4485 48086 : store_lock(store);
4486 48086 : ulng oldest = store_timestamp(store);
4487 48086 : store_pending_changes(store, oldest, tr);
4488 48086 : store_unlock(store);
4489 48086 : MT_lock_unset(&store->commit);
4490 : }
4491 :
4492 114199 : if (ok == LOG_OK)
4493 194595 : ok = clean_predicates_and_propagate_to_parent(tr);
4494 :
4495 194583 : return (ok==LOG_OK)?SQL_OK:SQL_ERR;
4496 : }
4497 :
4498 : static sql_table *
4499 5 : find_table_by_columnid(sql_trans *tr, const char *schema, sqlid id)
4500 : {
4501 5 : sqlstore *store = tr->store;
4502 5 : sql_table *syscolumn = find_sql_table(tr, find_sql_schema(tr, schema), "_columns");
4503 :
4504 5 : oid rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"), &id, NULL);
4505 5 : if (!is_oid_nil(rid)) {
4506 5 : sqlid tid = store->table_api.column_find_sqlid(tr, find_sql_column(syscolumn, "table_id"), rid);
4507 5 : return sql_trans_find_table(tr, tid);
4508 : }
4509 : return NULL;
4510 : }
4511 :
4512 : static int
4513 7033 : sql_trans_drop_all_dependencies(sql_trans *tr, sqlid id, sql_dependency type)
4514 : {
4515 7033 : sqlid dep_id=0, t_id = -1;
4516 7033 : sht dep_type = 0;
4517 7033 : list *dep = sql_trans_get_dependents(tr, id, type, NULL);
4518 7033 : node *n;
4519 7033 : int res = LOG_OK;
4520 :
4521 7033 : if (!dep)
4522 : return -1;
4523 :
4524 7033 : n = dep->h;
4525 :
4526 7413 : while (n && !res) {
4527 380 : dep_id = *(sqlid*) n->data;
4528 380 : dep_type = (sql_dependency) *(sht*) n->next->data;
4529 :
4530 380 : if (!list_find_id(tr->dropped, dep_id)) {
4531 :
4532 376 : switch (dep_type) {
4533 0 : case SCHEMA_DEPENDENCY:
4534 0 : res = sql_trans_drop_schema(tr, dep_id, DROP_CASCADE);
4535 0 : break;
4536 56 : case TABLE_DEPENDENCY:
4537 : case VIEW_DEPENDENCY: {
4538 56 : sql_table *t = sql_trans_find_table(tr, dep_id);
4539 56 : if (t)
4540 56 : res = sql_trans_drop_table_id(tr, t->s, dep_id, DROP_CASCADE);
4541 : } break;
4542 0 : case COLUMN_DEPENDENCY: {
4543 0 : if ((t_id = sql_trans_get_dependency_type(tr, dep_id, TABLE_DEPENDENCY)) > 0) {
4544 0 : sql_table *t = sql_trans_find_table(tr, dep_id);
4545 0 : if (t && ol_length(t->columns) == 1) /* only column left, drop the table instead */
4546 0 : res = sql_trans_drop_table_id(tr, t->s, t->base.id, DROP_CASCADE);
4547 0 : else if (t)
4548 0 : res = sql_trans_drop_column(tr, t, dep_id, DROP_CASCADE);
4549 : }
4550 : } break;
4551 2 : case TRIGGER_DEPENDENCY: {
4552 2 : sql_trigger *t = sql_trans_find_trigger(tr, dep_id);
4553 2 : if (t && !list_find_id(tr->dropped, t->t->base.id)) /* table not yet dropped */
4554 2 : res = sql_trans_drop_trigger(tr, t->t->s, dep_id, DROP_CASCADE);
4555 : } break;
4556 278 : case KEY_DEPENDENCY:
4557 : case FKEY_DEPENDENCY: {
4558 278 : sql_key *k = sql_trans_find_key(tr, dep_id);
4559 278 : if (k && !list_find_id(tr->dropped, k->t->base.id)) /* table not yet dropped */
4560 277 : res = sql_trans_drop_key(tr, k->t->s, dep_id, DROP_CASCADE);
4561 : } break;
4562 8 : case INDEX_DEPENDENCY: {
4563 8 : sql_idx *i = sql_trans_find_idx(tr, dep_id);
4564 8 : if (i && !list_find_id(tr->dropped, i->t->base.id)) /* table not yet dropped */
4565 8 : res = sql_trans_drop_idx(tr, i->t->s, dep_id, DROP_CASCADE);
4566 : } break;
4567 18 : case PROC_DEPENDENCY:
4568 : case FUNC_DEPENDENCY: {
4569 18 : sql_func *f = sql_trans_find_func(tr, dep_id);
4570 18 : if (f)
4571 18 : res = sql_trans_drop_func(tr, f->s, dep_id, DROP_CASCADE);
4572 : } break;
4573 14 : case TYPE_DEPENDENCY: {
4574 : /* Unlike other dependencies, for type dependencies,
4575 : the dependent object depends on the type, rather the other way around.
4576 : At this moment, only functions or columns depend on types, so try both */
4577 14 : sql_table *t = NULL;
4578 14 : sql_func *f = sql_trans_find_func(tr, dep_id);
4579 14 : if (f) {
4580 9 : res = sql_trans_drop_func(tr, f->s, dep_id, DROP_CASCADE);
4581 5 : } else if ((t = find_table_by_columnid(tr, "sys", dep_id)) ||
4582 0 : (t = find_table_by_columnid(tr, "tmp", dep_id))) {
4583 5 : if (ol_length(t->columns) == 1) /* only column left, drop the table instead */
4584 2 : res = sql_trans_drop_table_id(tr, t->s, t->base.id, DROP_CASCADE);
4585 : else
4586 3 : res = sql_trans_drop_column(tr, t, dep_id, DROP_CASCADE);
4587 : }
4588 : } break;
4589 : case USER_DEPENDENCY: /*TODO schema and users dependencies*/
4590 : break;
4591 : }
4592 : }
4593 :
4594 380 : n = n->next->next;
4595 : }
4596 7033 : list_destroy(dep);
4597 7033 : return res;
4598 : }
4599 :
4600 : static int
4601 2672 : sys_drop_ic(sql_trans *tr, sql_idx * i, sql_kc *kc)
4602 : {
4603 2672 : sqlstore *store = tr->store;
4604 2727 : sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
4605 2672 : sql_table *sysic = find_sql_table(tr, syss, "objects");
4606 2672 : oid rid = store->table_api.column_find_row(tr, find_sql_column(sysic, "id"), &i->base.id, find_sql_column(sysic, "name"), kc->c->base.name, NULL);
4607 2672 : int res = LOG_OK;
4608 :
4609 2672 : if (is_oid_nil(rid))
4610 : return -1;
4611 2672 : if ((res = store->table_api.table_delete(tr, sysic, rid)))
4612 : return res;
4613 : return res;
4614 : }
4615 :
4616 : static int
4617 38752 : sql_trans_drop_any_comment(sql_trans *tr, sqlid id)
4618 : {
4619 38752 : sqlstore *store = tr->store;
4620 38752 : sql_table *comments;
4621 38752 : sql_column *id_col;
4622 38752 : oid row;
4623 :
4624 38752 : comments = find_sql_table(tr, find_sql_schema(tr, "sys"), "comments");
4625 38752 : if (!comments) /* for example during upgrades */
4626 : return 0;
4627 :
4628 38752 : id_col = find_sql_column(comments, "id");
4629 38752 : assert(id_col);
4630 :
4631 38752 : row = store->table_api.column_find_row(tr, id_col, &id, NULL);
4632 38752 : if (!is_oid_nil(row) && store->table_api.table_delete(tr, comments, row))
4633 : return -2;
4634 : return 0;
4635 : }
4636 :
4637 : static int
4638 2179 : sys_drop_idx(sql_trans *tr, sql_idx * i, int drop_action)
4639 : {
4640 2179 : sqlstore *store = tr->store;
4641 2179 : node *n;
4642 2223 : sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
4643 2179 : sql_table *sysidx = find_sql_table(tr, syss, "idxs");
4644 2179 : oid rid = store->table_api.column_find_row(tr, find_sql_column(sysidx, "id"), &i->base.id, NULL);
4645 2179 : int res = LOG_OK;
4646 :
4647 2179 : if (is_oid_nil(rid))
4648 : return -1;
4649 2179 : if ((res = store->table_api.table_delete(tr, sysidx, rid)))
4650 : return res;
4651 2179 : if ((res = sql_trans_drop_any_comment(tr, i->base.id)))
4652 : return res;
4653 4851 : for (n = i->columns->h; n; n = n->next) {
4654 2672 : sql_kc *ic = n->data;
4655 :
4656 2672 : if (i->key && hash_index(i->type)) { /* update new column's unique value */
4657 1552 : int unique = 0;
4658 1552 : sqlid cid = ic->c->base.id;
4659 1552 : struct os_iter oi;
4660 :
4661 1552 : os_iterator(&oi, i->t->s->idxs, tr, NULL);
4662 44652 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
4663 43100 : sql_idx *ti = (sql_idx*)b;
4664 :
4665 43100 : if (ti->base.id != i->base.id && ti->key && hash_index(ti->type)) {
4666 35583 : bool found = false;
4667 77332 : for (node *m = ti->columns->h; m && !found; m = m->next) {
4668 41749 : sql_kc *tic = m->data;
4669 :
4670 41749 : found |= tic->c->base.id == cid;
4671 : }
4672 35583 : if (found)
4673 35 : unique = MAX(unique, list_length(ti->columns) == 1 ? 2 : 1);
4674 : }
4675 : }
4676 1552 : ic->c->unique = unique;
4677 : }
4678 2672 : if ((res = sys_drop_ic(tr, i, ic)))
4679 0 : return res;
4680 : }
4681 :
4682 2179 : i->base.deleted = 1;
4683 2179 : if (!isNew(i) && !isTempTable(i->t))
4684 1977 : if ((res = store->storage_api.drop_idx(tr, (sql_idx*)dup_base(&i->base))))
4685 : return res;
4686 :
4687 : /* remove idx from schema and table */
4688 2179 : if (isGlobal(i->t) && (res = os_del(i->t->s->idxs, tr, i->base.name, dup_base(&i->base))))
4689 : return res;
4690 2179 : if (!isNew(i) && (res = sql_trans_add_dependency_change(tr, i->base.id, ddl)))
4691 : return res;
4692 2179 : if ((res = sql_trans_drop_dependencies(tr, i->base.id)))
4693 : return res;
4694 :
4695 2179 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, i->base.id, INDEX_DEPENDENCY)))
4696 : return res;
4697 : return res;
4698 : }
4699 :
4700 : static int
4701 2353 : sys_drop_kc(sql_trans *tr, sql_key *k, sql_kc *kc)
4702 : {
4703 2353 : sqlstore *store = tr->store;
4704 2384 : sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
4705 2353 : sql_table *syskc = find_sql_table(tr, syss, "objects");
4706 2353 : oid rid = store->table_api.column_find_row(tr, find_sql_column(syskc, "id"), &k->base.id, find_sql_column(syskc, "name"), kc->c->base.name, NULL);
4707 2353 : int res = LOG_OK;
4708 :
4709 2353 : if (is_oid_nil(rid))
4710 : return -1;
4711 2353 : if ((res = store->table_api.table_delete(tr, syskc, rid)))
4712 : return res;
4713 : return res;
4714 : }
4715 :
4716 : static int
4717 1928 : sys_drop_key(sql_trans *tr, sql_key *k, int drop_action)
4718 : {
4719 1928 : sqlstore *store = tr->store;
4720 1928 : node *n;
4721 1959 : sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
4722 1928 : sql_table *syskey = find_sql_table(tr, syss, "keys");
4723 1928 : oid rid = store->table_api.column_find_row(tr, find_sql_column(syskey, "id"), &k->base.id, NULL);
4724 1928 : int res = LOG_OK;
4725 :
4726 1928 : if (is_oid_nil(rid))
4727 : return -1;
4728 1928 : if ((res = store->table_api.table_delete(tr, syskey, rid)))
4729 : return res;
4730 :
4731 4281 : for (n = k->columns->h; n; n = n->next) {
4732 2353 : sql_kc *kc = n->data;
4733 2353 : if ((res = sys_drop_kc(tr, k, kc)))
4734 0 : return res;
4735 : }
4736 : /* remove key from schema */
4737 1928 : if (isGlobal(k->t) && (res = os_del(k->t->s->keys, tr, k->base.name, dup_base(&k->base))))
4738 : return res;
4739 1928 : if (isGlobal(k->t) && (res = os_del(tr->cat->objects, tr, k->base.name, dup_base(&k->base))))
4740 : return res;
4741 1928 : if (k->t->pkey == (sql_ukey*)k)
4742 944 : k->t->pkey = NULL;
4743 :
4744 1928 : if (!isNew(k) && (res = sql_trans_add_dependency_change(tr, k->base.id, ddl)))
4745 : return res;
4746 1928 : if ((res = sql_trans_drop_dependencies(tr, k->base.id)))
4747 : return res;
4748 :
4749 2163 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, k->base.id, (k->type == fkey) ? FKEY_DEPENDENCY : KEY_DEPENDENCY)))
4750 : return res;
4751 : return res;
4752 : }
4753 :
4754 : static int
4755 0 : sys_drop_tc(sql_trans *tr, sql_trigger * i, sql_kc *kc)
4756 : {
4757 0 : sqlstore *store = tr->store;
4758 0 : sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
4759 0 : sql_table *systc = find_sql_table(tr, syss, "objects");
4760 0 : oid rid = store->table_api.column_find_row(tr, find_sql_column(systc, "id"), &i->base.id, find_sql_column(systc, "name"), kc->c->base.name, NULL);
4761 0 : int res = LOG_OK;
4762 :
4763 0 : if (is_oid_nil(rid))
4764 : return -1;
4765 0 : if ((res = store->table_api.table_delete(tr, systc, rid)))
4766 : return res;
4767 : return res;
4768 : }
4769 :
4770 : static int
4771 208 : sys_drop_sequence(sql_trans *tr, sql_sequence * seq, int drop_action)
4772 : {
4773 208 : if (!seq)
4774 : return -1;
4775 208 : sqlstore *store = tr->store;
4776 208 : sql_schema *syss = find_sql_schema(tr, "sys");
4777 208 : sql_table *sysseqs = find_sql_table(tr, syss, "sequences");
4778 208 : oid rid = store->table_api.column_find_row(tr, find_sql_column(sysseqs, "id"), &seq->base.id, NULL);
4779 208 : int res = LOG_OK;
4780 :
4781 208 : if (is_oid_nil(rid))
4782 : return -1;
4783 :
4784 208 : if ((res = store->table_api.table_delete(tr, sysseqs, rid)))
4785 : return res;
4786 208 : if (!isNew(seq) && (res = sql_trans_add_dependency_change(tr, seq->base.id, ddl)))
4787 : return res;
4788 208 : if ((res = sql_trans_drop_dependencies(tr, seq->base.id)))
4789 : return res;
4790 208 : if ((res = sql_trans_drop_any_comment(tr, seq->base.id)))
4791 : return res;
4792 208 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, seq->base.id, SEQ_DEPENDENCY)))
4793 : return res;
4794 : return res;
4795 : }
4796 :
4797 : static int
4798 31076 : sys_drop_default_object(sql_trans *tr, sql_column *col, int drop_action)
4799 : {
4800 31076 : const char next_value_for[] = "next value for ";
4801 31076 : int res = LOG_OK;
4802 :
4803 : /* Drop sequence for generated column if it's the case */
4804 31076 : if (col->def && !strncmp(col->def, next_value_for, strlen(next_value_for))) {
4805 167 : sql_schema *s = NULL;
4806 167 : sql_sequence *seq = NULL;
4807 167 : char *schema = NULL, *seq_name = NULL;
4808 :
4809 167 : extract_schema_and_sequence_name(NULL, col->def + strlen(next_value_for), &schema, &seq_name);
4810 167 : if (!schema || !seq_name || !(s = find_sql_schema(tr, schema))) {
4811 : /* didn't find the schema so no generated sequence */
4812 0 : _DELETE(schema);
4813 0 : _DELETE(seq_name);
4814 0 : return res;
4815 : }
4816 :
4817 167 : seq = find_sql_sequence(tr, s, seq_name);
4818 167 : _DELETE(schema);
4819 167 : _DELETE(seq_name);
4820 167 : if (seq && sql_trans_get_dependency_type(tr, seq->base.id, BEDROPPED_DEPENDENCY) > 0) {
4821 146 : if ((res = sys_drop_sequence(tr, seq, drop_action)))
4822 : return res;
4823 146 : if ((res = os_del(s->seqs, tr, seq->base.name, dup_base(&seq->base))))
4824 : return res;
4825 : }
4826 : }
4827 : return res;
4828 : }
4829 :
4830 : static int
4831 36365 : sql_trans_drop_obj_priv(sql_trans *tr, sqlid obj_id)
4832 : {
4833 36365 : sqlstore *store = tr->store;
4834 36365 : sql_schema *sys = find_sql_schema(tr, "sys");
4835 36365 : sql_table *privs = find_sql_table(tr, sys, "privileges");
4836 36365 : int res = LOG_OK;
4837 :
4838 36365 : assert(sys && privs);
4839 : /* select privileges of this obj_id */
4840 36365 : rids *A = store->table_api.rids_select(tr, find_sql_column(privs, "obj_id"), &obj_id, &obj_id, NULL);
4841 36365 : if (A == NULL)
4842 : return LOG_ERR;
4843 : /* remove them */
4844 36763 : for(oid rid = store->table_api.rids_next(A); !is_oid_nil(rid) && res == LOG_OK; rid = store->table_api.rids_next(A))
4845 398 : res = store->table_api.table_delete(tr, privs, rid);
4846 36365 : store->table_api.rids_destroy(A);
4847 36365 : return res;
4848 : }
4849 :
4850 : static int
4851 103 : sys_drop_trigger(sql_trans *tr, sql_trigger * i)
4852 : {
4853 103 : sqlstore *store = tr->store;
4854 103 : node *n;
4855 206 : sql_schema *syss = find_sql_schema(tr, (!i->t || isGlobal(i->t))?"sys":"tmp");
4856 103 : sql_table *systrigger = find_sql_table(tr, syss, "triggers");
4857 103 : oid rid = store->table_api.column_find_row(tr, find_sql_column(systrigger, "id"), &i->base.id, NULL);
4858 103 : int res = LOG_OK;
4859 :
4860 103 : if (is_oid_nil(rid))
4861 : return -1;
4862 103 : if ((res = store->table_api.table_delete(tr, systrigger, rid)))
4863 : return res;
4864 :
4865 100 : if (i->t) {
4866 97 : for (n = i->columns->h; n; n = n->next) {
4867 0 : sql_kc *tc = n->data;
4868 :
4869 0 : if ((res = sys_drop_tc(tr, i, tc)))
4870 0 : return res;
4871 : }
4872 : }
4873 : /* remove trigger from schema */
4874 100 : if ((res = os_del(i->t?i->t->s->triggers:syss->triggers, tr, i->base.name, dup_base(&i->base))))
4875 : return res;
4876 100 : if (!isNew(i) && (res = sql_trans_add_dependency_change(tr, i->base.id, ddl)))
4877 : return res;
4878 100 : if ((res = sql_trans_drop_dependencies(tr, i->base.id)))
4879 : return res;
4880 : return res;
4881 : }
4882 :
4883 : static int
4884 31053 : sys_drop_column(sql_trans *tr, sql_column *col, int drop_action)
4885 : {
4886 31053 : sqlstore *store = tr->store;
4887 31153 : sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
4888 31053 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
4889 31053 : oid rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"), &col->base.id, NULL);
4890 31053 : int res = LOG_OK;
4891 :
4892 31053 : if (is_oid_nil(rid))
4893 : return -1;
4894 31053 : if ((res = store->table_api.table_delete(tr, syscolumn, rid)))
4895 : return res;
4896 31053 : if (!isNew(col) && (res = sql_trans_add_dependency_change(tr, col->base.id, ddl)))
4897 : return res;
4898 31053 : if ((res = sql_trans_drop_dependencies(tr, col->base.id)))
4899 : return res;
4900 31053 : if ((res = sql_trans_drop_any_comment(tr, col->base.id)))
4901 : return res;
4902 31053 : if ((res = sql_trans_drop_obj_priv(tr, col->base.id)))
4903 : return res;
4904 31053 : if ((res = sys_drop_default_object(tr, col, drop_action)))
4905 : return res;
4906 :
4907 31053 : if (col->type.multiset && col->storage_type &&
4908 31 : ((res = sql_trans_drop_table(tr, col->t->s, col->storage_type, drop_action)) ||
4909 31 : (res = sql_trans_drop_sequence(tr, col->t->s, find_sql_sequence(tr, col->t->s, col->storage_type), drop_action))))
4910 0 : return res;
4911 :
4912 31053 : col->base.deleted = 1;
4913 31053 : if (!isNew(col) && !isTempTable(col->t))
4914 19626 : if ((res = store->storage_api.drop_col(tr, (sql_column*)dup_base(&col->base))))
4915 : return res;
4916 :
4917 31053 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, col->base.id, COLUMN_DEPENDENCY)))
4918 : return res;
4919 31053 : if (col->type.type->s && (res = sql_trans_drop_dependency(tr, col->type.type->base.id, col->base.id, TYPE_DEPENDENCY)))
4920 : return res;
4921 : return res;
4922 : }
4923 :
4924 : static int
4925 4395 : sys_drop_keys(sql_trans *tr, sql_table *t, int drop_action)
4926 : {
4927 4395 : node *n;
4928 4395 : int res = LOG_OK;
4929 :
4930 4395 : if (ol_length(t->keys))
4931 2581 : for (n = ol_first_node(t->keys); n; n = n->next) {
4932 1505 : sql_key *k = n->data;
4933 :
4934 1505 : if ((res = sys_drop_key(tr, k, drop_action)))
4935 0 : return res;
4936 : }
4937 : return res;
4938 : }
4939 :
4940 : static int
4941 4395 : sys_drop_idxs(sql_trans *tr, sql_table *t, int drop_action)
4942 : {
4943 4395 : node *n;
4944 4395 : int res = LOG_OK;
4945 :
4946 4395 : if (ol_length(t->idxs))
4947 2696 : for (n = ol_first_node(t->idxs); n; n = n->next) {
4948 1597 : sql_idx *k = n->data;
4949 :
4950 1597 : if ((res = sys_drop_idx(tr, k, drop_action)))
4951 0 : return res;
4952 : }
4953 : return res;
4954 : }
4955 :
4956 : static int
4957 4395 : sys_drop_triggers(sql_trans *tr, sql_table *t)
4958 : {
4959 4395 : node *n;
4960 4395 : int res = LOG_OK;
4961 :
4962 4395 : if (ol_length(t->triggers))
4963 21 : for (n = ol_first_node(t->triggers); n; n = n->next) {
4964 12 : sql_trigger *i = n->data;
4965 :
4966 12 : if ((res = sys_drop_trigger(tr, i)))
4967 0 : return res;
4968 : }
4969 : return res;
4970 : }
4971 :
4972 : static int
4973 4395 : sys_drop_columns(sql_trans *tr, sql_table *t, int drop_action)
4974 : {
4975 4395 : node *n;
4976 4395 : int res = LOG_OK;
4977 :
4978 4395 : if (ol_length(t->columns))
4979 35378 : for (n = t->columns->l->h; n; n = n->next) {
4980 30983 : sql_column *c = n->data;
4981 :
4982 30983 : if ((res = sys_drop_column(tr, c, drop_action)))
4983 0 : return res;
4984 : }
4985 : return res;
4986 : }
4987 :
4988 : static int
4989 293 : sys_drop_part(sql_trans *tr, sql_part *pt, int drop_action)
4990 : {
4991 293 : sqlstore *store = tr->store;
4992 293 : sql_table *mt = pt->t;
4993 293 : sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
4994 293 : sql_table *sysobj = find_sql_table(tr, syss, "objects");
4995 293 : oid obj_oid = store->table_api.column_find_row(tr, find_sql_column(sysobj, "id"), &pt->base.id, NULL);
4996 293 : int res = LOG_OK;
4997 :
4998 293 : (void)drop_action;
4999 293 : if (is_oid_nil(obj_oid))
5000 : return -1;
5001 :
5002 293 : if ((res = store->table_api.table_delete(tr, sysobj, obj_oid)))
5003 : return res;
5004 293 : if (isRangePartitionTable(mt)) {
5005 93 : if (isPartitionedByColumnTable(pt->t))
5006 80 : col_set_range(tr, pt, false);
5007 93 : sql_table *ranges = find_sql_table(tr, syss, "range_partitions");
5008 93 : assert(ranges);
5009 93 : oid rid = store->table_api.column_find_row(tr, find_sql_column(ranges, "table_id"), &pt->member, NULL);
5010 93 : if ((res = store->table_api.table_delete(tr, ranges, rid)))
5011 : return res;
5012 200 : } else if (isListPartitionTable(mt)) {
5013 25 : sql_table *values = find_sql_table(tr, syss, "value_partitions");
5014 25 : assert(values);
5015 25 : rids *rs = store->table_api.rids_select(tr, find_sql_column(values, "table_id"), &pt->member, &pt->member, NULL);
5016 25 : if (rs == NULL)
5017 : return LOG_ERR;
5018 107 : for (oid rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
5019 82 : if ((res = store->table_api.table_delete(tr, values, rid))) {
5020 0 : store->table_api.rids_destroy(rs);
5021 0 : return res;
5022 : }
5023 : }
5024 25 : store->table_api.rids_destroy(rs);
5025 : }
5026 : /* merge table depends on part table */
5027 293 : if (!isNew(pt) && (res = sql_trans_add_dependency_change(tr, mt->base.id, ddl)))
5028 : return res;
5029 293 : if ((res = sql_trans_drop_dependency(tr, pt->member, mt->base.id, TABLE_DEPENDENCY)))
5030 : return res;
5031 :
5032 293 : if ((res = os_del(mt->s->parts, tr, pt->base.name, dup_base(&pt->base))))
5033 : return res;
5034 : return res;
5035 : }
5036 :
5037 : static int
5038 199 : sys_drop_members(sql_trans *tr, sql_table *t, int drop_action)
5039 : {
5040 199 : int res = LOG_OK;
5041 :
5042 199 : if (!list_empty(t->members)) {
5043 181 : for (node *n = t->members->h; n; ) {
5044 102 : sql_part *pt = n->data;
5045 :
5046 102 : n = n->next;
5047 102 : if ((res = sys_drop_part(tr, pt, drop_action)))
5048 0 : return res;
5049 : }
5050 : }
5051 : return res;
5052 : }
5053 :
5054 : static int
5055 21 : sys_drop_parts(sql_trans *tr, sql_table *t, int drop_action)
5056 : {
5057 21 : int res = LOG_OK;
5058 :
5059 42 : for(sql_part *pt = partition_find_part(tr, t, NULL); pt; pt = partition_find_part(tr, t, pt)) {
5060 21 : if ((res = sql_trans_del_table(tr, pt->t, t, drop_action)))
5061 0 : return res;
5062 : }
5063 : return res;
5064 : }
5065 :
5066 : static int
5067 4395 : sys_drop_table(sql_trans *tr, sql_table *t, int drop_action)
5068 : {
5069 4395 : sqlstore *store = tr->store;
5070 4450 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
5071 4395 : sql_table *systable = find_sql_table(tr, syss, "_tables");
5072 4395 : sql_column *syscol = find_sql_column(systable, "id");
5073 4395 : oid rid = store->table_api.column_find_row(tr, syscol, &t->base.id, NULL);
5074 4395 : int res = LOG_OK;
5075 :
5076 4395 : if (is_oid_nil(rid))
5077 : return -1;
5078 :
5079 4395 : if ((res = store->table_api.table_delete(tr, systable, rid)))
5080 : return res;
5081 4395 : if ((res = sys_drop_keys(tr, t, drop_action)))
5082 : return res;
5083 4395 : if ((res = sys_drop_idxs(tr, t, drop_action)))
5084 : return res;
5085 4395 : if ((res = sys_drop_triggers(tr, t)))
5086 : return res;
5087 :
5088 4395 : if (partition_find_part(tr, t, NULL))
5089 21 : if ((res = sys_drop_parts(tr, t, drop_action)))
5090 : return res;
5091 :
5092 4395 : if (isMergeTable(t) || isReplicaTable(t))
5093 199 : if ((res = sys_drop_members(tr, t, drop_action)))
5094 : return res;
5095 :
5096 4395 : if (isRangePartitionTable(t) || isListPartitionTable(t)) {
5097 66 : sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
5098 66 : assert(partitions);
5099 66 : sql_column *pcols = find_sql_column(partitions, "table_id");
5100 66 : assert(pcols);
5101 66 : rids *rs = store->table_api.rids_select(tr, pcols, &t->base.id, &t->base.id, NULL);
5102 66 : if (!rs)
5103 : return -1;
5104 66 : oid poid;
5105 66 : if (rs == NULL)
5106 : return LOG_ERR;
5107 66 : if ((poid = store->table_api.rids_next(rs)) != oid_nil) {
5108 66 : if ((res = store->table_api.table_delete(tr, partitions, poid))) {
5109 0 : store->table_api.rids_destroy(rs);
5110 0 : return res;
5111 : }
5112 : }
5113 66 : store->table_api.rids_destroy(rs);
5114 : }
5115 :
5116 4395 : if ((res = sql_trans_drop_any_comment(tr, t->base.id)))
5117 : return res;
5118 4395 : if (!isNew(t) && (res = sql_trans_add_dependency_change(tr, t->base.id, ddl)))
5119 : return res;
5120 4395 : if ((res = sql_trans_drop_dependencies(tr, t->base.id)))
5121 : return res;
5122 4395 : if ((res = sql_trans_drop_obj_priv(tr, t->base.id)))
5123 : return res;
5124 4395 : if ((res = sys_drop_columns(tr, t, drop_action)))
5125 : return res;
5126 :
5127 4395 : if (isTable(t) && !isNew(t))
5128 3434 : if ((res = store->storage_api.drop_del(tr, t)))
5129 : return res;
5130 :
5131 4610 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, t->base.id, !isView(t) ? TABLE_DEPENDENCY : VIEW_DEPENDENCY)))
5132 : return res;
5133 : return res;
5134 : }
5135 :
5136 : static int
5137 39 : sys_drop_type(sql_trans *tr, sql_type *type, int drop_action)
5138 : {
5139 39 : sqlstore *store = tr->store;
5140 39 : sql_schema *syss = find_sql_schema(tr, "sys");
5141 39 : sql_table *sys_tab_type = find_sql_table(tr, syss, "types");
5142 39 : sql_column *sys_type_col = find_sql_column(sys_tab_type, "id");
5143 39 : oid rid = store->table_api.column_find_row(tr, sys_type_col, &type->base.id, NULL);
5144 39 : int res = LOG_OK;
5145 :
5146 39 : if (is_oid_nil(rid))
5147 : return -1;
5148 39 : if (type->composite) {
5149 36 : sql_table *sys_tab_fields = find_sql_table(tr, syss, "args");
5150 36 : sql_column *sys_fields_col = find_sql_column(sys_tab_fields, "func_id");
5151 36 : rids *fields = store->table_api.rids_select(tr, sys_fields_col, &type->base.id, &type->base.id, NULL);
5152 :
5153 36 : if (fields == NULL)
5154 : return LOG_ERR;
5155 116 : for (oid r = store->table_api.rids_next(fields); !is_oid_nil(r); r = store->table_api.rids_next(fields)) {
5156 80 : if ((res = store->table_api.table_delete(tr, sys_tab_fields, r))) {
5157 0 : store->table_api.rids_destroy(fields);
5158 0 : return res;
5159 : }
5160 : }
5161 36 : store->table_api.rids_destroy(fields);
5162 : }
5163 :
5164 39 : if ((res = store->table_api.table_delete(tr, sys_tab_type, rid)))
5165 : return res;
5166 :
5167 39 : if (!isNew(type) && (res = sql_trans_add_dependency_change(tr, type->base.id, ddl)))
5168 : return res;
5169 39 : if ((res = sql_trans_drop_dependencies(tr, type->base.id)))
5170 : return res;
5171 :
5172 39 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, type->base.id, TYPE_DEPENDENCY)))
5173 : return res;
5174 : return res;
5175 : }
5176 :
5177 : static int
5178 757 : sys_drop_func(sql_trans *tr, sql_func *func, int drop_action)
5179 : {
5180 757 : sqlstore *store = tr->store;
5181 757 : sql_schema *syss = find_sql_schema(tr, "sys");
5182 757 : sql_table *sys_tab_func = find_sql_table(tr, syss, "functions");
5183 757 : sql_column *sys_func_col = find_sql_column(sys_tab_func, "id");
5184 757 : oid rid_func = store->table_api.column_find_row(tr, sys_func_col, &func->base.id, NULL);
5185 757 : if (is_oid_nil(rid_func))
5186 : return -1;
5187 757 : sql_table *sys_tab_args = find_sql_table(tr, syss, "args");
5188 757 : sql_column *sys_args_col = find_sql_column(sys_tab_args, "func_id");
5189 757 : rids *args = store->table_api.rids_select(tr, sys_args_col, &func->base.id, &func->base.id, NULL);
5190 757 : int res = LOG_OK;
5191 :
5192 757 : if (args == NULL)
5193 : return LOG_ERR;
5194 2822 : for (oid r = store->table_api.rids_next(args); !is_oid_nil(r); r = store->table_api.rids_next(args)) {
5195 2066 : if ((res = store->table_api.table_delete(tr, sys_tab_args, r))) {
5196 1 : store->table_api.rids_destroy(args);
5197 1 : return res;
5198 : }
5199 : }
5200 756 : store->table_api.rids_destroy(args);
5201 :
5202 756 : assert(!is_oid_nil(rid_func));
5203 756 : if ((res = store->table_api.table_delete(tr, sys_tab_func, rid_func)))
5204 : return res;
5205 :
5206 756 : if (!isNew(func) && (res = sql_trans_add_dependency_change(tr, func->base.id, ddl)))
5207 : return res;
5208 756 : if ((res = sql_trans_drop_dependencies(tr, func->base.id)))
5209 : return res;
5210 756 : if ((res = sql_trans_drop_any_comment(tr, func->base.id)))
5211 : return res;
5212 756 : if ((res = sql_trans_drop_obj_priv(tr, func->base.id)))
5213 : return res;
5214 :
5215 833 : if (drop_action && (res = sql_trans_drop_all_dependencies(tr, func->base.id, !IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY)))
5216 : return res;
5217 756 : if (!func->vararg && func->ops) {
5218 1803 : for (node *n = func->ops->h; n; n = n->next) {
5219 1050 : sql_arg *a = n->data;
5220 :
5221 1050 : if (a->type.type->s && (res = sql_trans_drop_dependency(tr, a->type.type->base.id, func->base.id, TYPE_DEPENDENCY)))
5222 0 : return res;
5223 : }
5224 : }
5225 756 : if (!func->varres && func->res) {
5226 1681 : for (node *n = func->res->h; n; n = n->next) {
5227 1015 : sql_arg *a = n->data;
5228 :
5229 1015 : if (a->type.type->s && (res = sql_trans_drop_dependency(tr, a->type.type->base.id, func->base.id, TYPE_DEPENDENCY)))
5230 0 : return res;
5231 : }
5232 : }
5233 : return res;
5234 : }
5235 :
5236 : static int
5237 161 : sys_drop_types(sql_trans *tr, sql_schema *s, int drop_action)
5238 : {
5239 161 : int res = LOG_OK;
5240 161 : struct os_iter oi;
5241 161 : os_iterator(&oi, s->types, tr, NULL);
5242 161 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
5243 0 : sql_type *t = (sql_type*)b;
5244 :
5245 0 : if ((res = sys_drop_type(tr, t, drop_action)))
5246 0 : return res;
5247 : }
5248 : return res;
5249 : }
5250 :
5251 : static int
5252 161 : sys_drop_tables(sql_trans *tr, sql_schema *s, int drop_action)
5253 : {
5254 161 : int res = LOG_OK;
5255 161 : struct os_iter oi;
5256 161 : os_iterator(&oi, s->tables, tr, NULL);
5257 206 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
5258 45 : sql_table *t = (sql_table*)b;
5259 :
5260 45 : if ((res = sys_drop_table(tr, t, drop_action)))
5261 0 : return res;
5262 : }
5263 : return res;
5264 : }
5265 :
5266 : static int
5267 161 : sys_drop_funcs(sql_trans *tr, sql_schema *s, int drop_action)
5268 : {
5269 161 : int res = LOG_OK;
5270 161 : struct os_iter oi;
5271 161 : os_iterator(&oi, s->funcs, tr, NULL);
5272 181 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
5273 20 : sql_func *f = (sql_func*)b;
5274 :
5275 20 : if ((res = sys_drop_func(tr, f, drop_action)))
5276 0 : return res;
5277 : }
5278 : return res;
5279 : }
5280 :
5281 : static int
5282 161 : sys_drop_sequences(sql_trans *tr, sql_schema *s, int drop_action)
5283 : {
5284 161 : int res = LOG_OK;
5285 161 : struct os_iter oi;
5286 161 : os_iterator(&oi, s->seqs, tr, NULL);
5287 162 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
5288 1 : sql_sequence *seq = (sql_sequence*)b;
5289 :
5290 1 : if ((res = sys_drop_sequence(tr, seq, drop_action)))
5291 0 : return res;
5292 : }
5293 : return res;
5294 : }
5295 :
5296 : int
5297 963 : sql_trans_create_type(sql_trans *tr, sql_schema *s, const char *sqlname, unsigned int digits, unsigned int scale, int radix, const char *impl, list *fields)
5298 : {
5299 963 : (void)fields;
5300 963 : sqlstore *store = tr->store;
5301 963 : sql_type *t;
5302 963 : sql_table *systype;
5303 963 : int localtype = impl?ATOMindex(impl) : TYPE_int, number = 0;
5304 963 : sql_class eclass = EC_EXTERNAL;
5305 963 : int eclass_cast = (int) eclass, res = LOG_OK;
5306 :
5307 963 : if (localtype < 0)
5308 : return -4;
5309 963 : t = ZNEW(sql_type);
5310 963 : sql_schema *syss = find_sql_schema(tr, "sys");
5311 963 : systype = find_sql_table(tr, syss, "types");
5312 963 : base_init(NULL, &t->base, next_oid(tr->store), true, sqlname);
5313 963 : t->d.impl = impl ? _STRDUP(impl) : NULL;
5314 963 : if (fields) {
5315 37 : t->composite = true;
5316 37 : t->d.fields = list_create((fdestroy) &arg_destroy);
5317 119 : for (node *n=fields->h; n; n = n->next)
5318 82 : list_append(t->d.fields, arg_dup(tr, s, n->data));
5319 : }
5320 963 : t->digits = digits;
5321 963 : t->scale = scale;
5322 963 : t->radix = radix;
5323 963 : t->eclass = eclass;
5324 963 : t->localtype = localtype;
5325 963 : t->s = s;
5326 :
5327 963 : if ((res = os_add(s->types, tr, t->base.name, &t->base)))
5328 : return res;
5329 962 : char *strnil = (char*)ATOMnilptr(TYPE_str);
5330 962 : if ((res = store->table_api.table_insert(tr, systype, &t->base.id, t->composite ? &strnil : &t->d.impl, &t->base.name, &t->digits, &t->scale, &radix, &eclass_cast, &s->base.id)))
5331 : return res;
5332 962 : if (t->composite) {
5333 37 : sql_table *sysarg = find_sql_table(tr, syss, "args");
5334 119 : for (node *n = t->d.fields->h; n; n = n->next, number++) {
5335 82 : sql_arg *a = n->data;
5336 82 : sqlid id = next_oid(tr->store);
5337 :
5338 82 : if (a->type.type->composite)
5339 25 : if ((res = sql_trans_create_dependency(tr, a->type.type->base.id, t->base.id, TYPE_DEPENDENCY)))
5340 0 : return res;
5341 :
5342 82 : if ((res = store->table_api.table_insert(tr, sysarg, &id, &t->base.id, &a->name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &number, &a->type.multiset)))
5343 0 : return res;
5344 : }
5345 : }
5346 : return res;
5347 : }
5348 :
5349 : int
5350 39 : sql_trans_drop_type(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
5351 : {
5352 39 : sql_type *t = sql_trans_find_type(tr, s, id);
5353 39 : int res = LOG_OK;
5354 :
5355 39 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
5356 1 : sqlid* local_id = MNEW(sqlid);
5357 1 : if (!local_id)
5358 : return -1;
5359 :
5360 1 : if (!tr->dropped) {
5361 1 : tr->dropped = list_create((fdestroy) &id_destroy);
5362 1 : if (!tr->dropped) {
5363 0 : _DELETE(local_id);
5364 0 : return -1;
5365 : }
5366 : }
5367 1 : *local_id = t->base.id;
5368 1 : list_append(tr->dropped, local_id);
5369 : }
5370 :
5371 39 : if ((res = sys_drop_type(tr, t, drop_action)))
5372 : return res;
5373 39 : if ((res = os_del(s->types, tr, t->base.name, dup_base(&t->base))))
5374 : return res;
5375 :
5376 39 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
5377 1 : list_destroy(tr->dropped);
5378 1 : tr->dropped = NULL;
5379 : }
5380 : return res;
5381 : }
5382 :
5383 : sql_func *
5384 124733 : create_sql_func(sqlstore *store, allocator *sa, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod,
5385 : const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect, bit order_required, bit opt_order)
5386 : {
5387 124733 : sql_func *t = SA_ZNEW(sa, sql_func);
5388 :
5389 124733 : base_init(sa, &t->base, next_oid(store), true, func);
5390 124733 : assert(mod);
5391 124733 : t->imp = (impl)?SA_STRDUP(sa, impl):NULL;
5392 124733 : t->mod = SA_STRDUP(sa, mod);
5393 124733 : t->type = type;
5394 124733 : t->lang = lang;
5395 124733 : t->instantiated = lang != FUNC_LANG_SQL && lang != FUNC_LANG_MAL;
5396 124733 : t->semantics = TRUE;
5397 124733 : t->side_effect = side_effect;
5398 124733 : t->varres = varres;
5399 124733 : t->vararg = vararg;
5400 124733 : t->ops = args;
5401 124733 : t->res = res;
5402 124733 : t->query = (query)?SA_STRDUP(sa, query):NULL;
5403 124733 : t->fix_scale = SCALE_EQ;
5404 124733 : t->s = NULL;
5405 124733 : t->system = system;
5406 124733 : t->order_required = order_required;
5407 124733 : t->opt_order = opt_order;
5408 124733 : return t;
5409 : }
5410 :
5411 : int
5412 125145 : sql_trans_create_func(sql_func **fres, sql_trans *tr, sql_schema *s, const char *func, list *args, list *ffres, sql_ftype type, sql_flang lang,
5413 : const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect, bit order_required, bit opt_order)
5414 : {
5415 125145 : sqlstore *store = tr->store;
5416 125145 : sql_schema *syss = find_sql_schema(tr, "sys");
5417 125145 : sql_table *sysfunc = find_sql_table(tr, syss, "functions");
5418 125145 : sql_table *sysarg = find_sql_table(tr, syss, "args");
5419 125145 : node *n;
5420 125145 : int number = 0, ftype = (int) type, flang = (int) lang, res = LOG_OK;
5421 125145 : bit semantics = TRUE;
5422 125145 : bte order_spec = order_required?2:opt_order?1:0;
5423 :
5424 125145 : sql_func *t = ZNEW(sql_func);
5425 125145 : base_init(NULL, &t->base, next_oid(tr->store), true, func);
5426 125145 : assert(mod);
5427 125145 : t->imp = (impl)?_STRDUP(impl):NULL;
5428 125145 : t->mod =_STRDUP(mod);
5429 125145 : t->type = type;
5430 125145 : t->lang = lang;
5431 125145 : t->instantiated = lang != FUNC_LANG_SQL && lang != FUNC_LANG_MAL;
5432 125145 : t->semantics = semantics;
5433 125145 : t->side_effect = side_effect;
5434 125145 : t->varres = varres;
5435 125145 : t->vararg = vararg;
5436 125145 : t->ops = list_create((fdestroy) &arg_destroy);
5437 125145 : t->fix_scale = SCALE_EQ;
5438 125145 : t->system = system;
5439 125145 : t->order_required = order_required;
5440 125145 : t->opt_order = opt_order;
5441 320405 : for (n=args->h; n; n = n->next)
5442 195260 : list_append(t->ops, arg_dup(tr, s, n->data));
5443 125145 : if (ffres) {
5444 105706 : t->res = list_create((fdestroy) &arg_destroy);
5445 268714 : for (n=ffres->h; n; n = n->next)
5446 163008 : list_append(t->res, arg_dup(tr, s, n->data));
5447 : }
5448 125145 : t->query = (query)?_STRDUP(query):NULL;
5449 125145 : t->s = s;
5450 :
5451 125145 : if ((res = os_add(s->funcs, tr, t->base.name, &t->base)))
5452 : return res;
5453 125144 : if ((res = store->table_api.table_insert(tr, sysfunc, &t->base.id, &t->base.name, query?(char**)&query:&t->imp, &t->mod, &flang, &ftype, &side_effect,
5454 : &varres, &vararg, &s->base.id, &system, &semantics, &order_spec)))
5455 : return res;
5456 288151 : if (t->res) for (n = t->res->h; n; n = n->next, number++) {
5457 163007 : sql_arg *a = n->data;
5458 163007 : sqlid id = next_oid(tr->store);
5459 163007 : if ((res = store->table_api.table_insert(tr, sysarg, &id, &t->base.id, &a->name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &number, &a->type.multiset)))
5460 0 : return res;
5461 : }
5462 320404 : if (t->ops) for (n = t->ops->h; n; n = n->next, number++) {
5463 195260 : sql_arg *a = n->data;
5464 195260 : sqlid id = next_oid(tr->store);
5465 195260 : if ((res = store->table_api.table_insert(tr, sysarg, &id, &t->base.id, &a->name, &a->type.type->base.name, &a->type.digits, &a->type.scale, &a->inout, &number, &a->type.multiset)))
5466 0 : return res;
5467 : }
5468 125144 : *fres = t;
5469 125144 : if (t->type == F_FILT && (list_length(t->ops) == 2 || list_length(t->ops) == 3))
5470 3208 : if (!find_keyword(t->base.name))
5471 2518 : (void) keywords_insert(t->base.name, KW_OPERATORS);
5472 : return res;
5473 : }
5474 :
5475 : int
5476 689 : sql_trans_drop_func(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
5477 : {
5478 689 : sql_base *b = os_find_id(s->funcs, tr, id);
5479 689 : int res = LOG_OK;
5480 :
5481 689 : if (!b)
5482 : return res;
5483 :
5484 689 : sql_func *func = (sql_func*)b;
5485 689 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
5486 85 : sqlid *local_id = MNEW(sqlid);
5487 85 : if (!local_id)
5488 : return -1;
5489 :
5490 85 : if (! tr->dropped) {
5491 58 : tr->dropped = list_create((fdestroy) &id_destroy);
5492 58 : if (!tr->dropped) {
5493 0 : _DELETE(local_id);
5494 0 : return -1;
5495 : }
5496 : }
5497 85 : *local_id = func->base.id;
5498 85 : list_append(tr->dropped, local_id);
5499 : }
5500 :
5501 689 : if ((res = sys_drop_func(tr, func, DROP_CASCADE)))
5502 : return res;
5503 688 : if ((res = os_del(s->funcs, tr, func->base.name, dup_base(&func->base))))
5504 : return res;
5505 :
5506 688 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
5507 58 : list_destroy(tr->dropped);
5508 58 : tr->dropped = NULL;
5509 : }
5510 : return res;
5511 : }
5512 :
5513 : static int
5514 48 : build_drop_func_list_item(sql_trans *tr, sql_schema *s, sqlid id)
5515 : {
5516 48 : sql_base *b = os_find_id(s->funcs, tr, id);
5517 48 : int res = LOG_OK;
5518 :
5519 48 : if (b) {
5520 48 : sql_func *func = (sql_func*)b;
5521 48 : if ((res = sys_drop_func(tr, func, DROP_CASCADE)))
5522 : return res;
5523 48 : if ((res = os_del(s->funcs, tr, func->base.name, dup_base(&func->base))))
5524 : return res;
5525 : }
5526 : return res;
5527 : }
5528 :
5529 : int
5530 36 : sql_trans_drop_all_func(sql_trans *tr, sql_schema *s, list *list_func, int drop_action)
5531 : {
5532 36 : list *to_drop = NULL;
5533 36 : int res = LOG_OK;
5534 :
5535 36 : (void) drop_action;
5536 36 : if (!tr->dropped && !(tr->dropped = list_create((fdestroy) &id_destroy)))
5537 : return -1;
5538 :
5539 84 : for (node *n = list_func->h; n ; n = n->next ) {
5540 48 : sql_func *func = (sql_func *) n->data;
5541 :
5542 48 : if (!list_find_id(tr->dropped, func->base.id)) {
5543 48 : sqlid *local_id = MNEW(sqlid);
5544 48 : if (!local_id) {
5545 0 : list_destroy(tr->dropped);
5546 0 : tr->dropped = NULL;
5547 0 : if (to_drop)
5548 0 : list_destroy(to_drop);
5549 0 : return -1;
5550 : }
5551 48 : if (!to_drop && !(to_drop = list_create(NULL))) {
5552 0 : list_destroy(tr->dropped);
5553 0 : tr->dropped = NULL;
5554 0 : return -1;
5555 : }
5556 48 : *local_id = func->base.id;
5557 48 : list_append(tr->dropped, local_id);
5558 48 : list_append(to_drop, func);
5559 : }
5560 : }
5561 :
5562 36 : if (to_drop) {
5563 84 : for (node *n = to_drop->h; n ; n = n->next ) {
5564 48 : sql_func *func = (sql_func *) n->data;
5565 48 : if ((res = build_drop_func_list_item(tr, s, func->base.id))) {
5566 0 : list_destroy(tr->dropped);
5567 0 : tr->dropped = NULL;
5568 0 : list_destroy(to_drop);
5569 0 : return res;
5570 : }
5571 : }
5572 36 : list_destroy(to_drop);
5573 : }
5574 :
5575 36 : list_destroy(tr->dropped);
5576 36 : tr->dropped = NULL;
5577 36 : return res;
5578 : }
5579 :
5580 : int
5581 1137 : sql_trans_create_schema(sql_trans *tr, const char *name, sqlid auth_id, sqlid owner, sqlid *schema_id_ptr)
5582 : {
5583 1137 : sqlstore *store = tr->store;
5584 1137 : sql_schema *s = ZNEW(sql_schema);
5585 1137 : sql_table *sysschema = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
5586 1137 : int res = LOG_OK;
5587 :
5588 1137 : base_init(NULL, &s->base, next_oid(tr->store), true, name);
5589 1137 : s->auth_id = auth_id;
5590 1137 : s->owner = owner;
5591 1137 : s->system = FALSE;
5592 1137 : assert(!isTempSchema(s)); // TODO transaction_layer_revamp: check if this is really true
5593 1137 : s->tables = os_new(NULL, (destroy_fptr) &table_destroy, false, true, true, false, store);
5594 1137 : s->types = os_new(NULL, (destroy_fptr) &type_destroy, false, true, true, false, store);
5595 1137 : s->funcs = os_new(NULL, (destroy_fptr) &func_destroy, false, false, false, false, store);
5596 1137 : s->seqs = os_new(NULL, (destroy_fptr) &seq_destroy, false, true, true, false, store);
5597 1137 : s->keys = os_new(NULL, (destroy_fptr) &key_destroy, false, true, true, false, store);
5598 1137 : s->idxs = os_new(NULL, (destroy_fptr) &idx_destroy, false, true, true, false, store);
5599 1137 : s->triggers = os_new(NULL, (destroy_fptr) &trigger_destroy, false, true, true, false, store);
5600 1137 : s->parts = os_new(NULL, (destroy_fptr) &part_destroy, false, false, true, false, store);
5601 1137 : s->store = tr->store;
5602 :
5603 1137 : if ((res = store->table_api.table_insert(tr, sysschema, &s->base.id, &s->base.name, &s->auth_id, &s->owner, &s->system))) {
5604 0 : schema_destroy(store, s);
5605 0 : return res;
5606 : }
5607 1137 : if ((res = os_add(tr->cat->schemas, tr, s->base.name, &s->base)))
5608 : return res;
5609 1136 : if ((res = sql_trans_add_dependency(tr, s->auth_id, ddl)))
5610 : return res;
5611 1136 : if ((res = sql_trans_add_dependency(tr, s->owner, ddl)))
5612 : return res;
5613 1136 : if (schema_id_ptr)
5614 33 : *schema_id_ptr = s->base.id;
5615 : return res;
5616 : }
5617 :
5618 : int
5619 8 : sql_trans_rename_schema(sql_trans *tr, sqlid id, const char *new_name)
5620 : {
5621 8 : sqlstore *store = tr->store;
5622 8 : table_functions table_api = store->table_api;
5623 8 : sql_table *schemas = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
5624 8 : sql_schema *s = find_sql_schema_id(tr, id), *ns = NULL;
5625 8 : oid rid;
5626 8 : int res = LOG_OK;
5627 :
5628 16 : assert(!strNil(new_name));
5629 :
5630 8 : rid = table_api.column_find_row(tr, find_sql_column(schemas, "id"), &id, NULL);
5631 8 : assert(!is_oid_nil(rid));
5632 8 : if ((res = table_api.column_update_value(tr, find_sql_column(schemas, "name"), rid, (void*) new_name)))
5633 : return res;
5634 :
5635 8 : if (!isNew(s) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
5636 : return res;
5637 :
5638 : /* delete schema, add schema */
5639 8 : if ((res = os_del(tr->cat->schemas, tr, s->base.name, dup_base(&s->base))))
5640 : return res;
5641 :
5642 8 : if ((res = schema_dup(tr, s, new_name, &ns)) ||
5643 8 : (res = os_add(tr->cat->schemas, tr, ns->base.name, &ns->base))) {
5644 0 : return res;
5645 : }
5646 :
5647 : return res;
5648 : }
5649 :
5650 : int
5651 32 : sql_trans_change_schema_authorization(sql_trans *tr, sqlid id, sqlid auth_id)
5652 : {
5653 32 : sqlstore *store = tr->store;
5654 32 : sql_table *sysschema = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
5655 32 : sql_schema *s = find_sql_schema_id(tr, id), *ns = NULL;
5656 32 : oid rid;
5657 32 : int res = LOG_OK;
5658 :
5659 32 : assert(auth_id);
5660 32 : s->auth_id = auth_id;
5661 :
5662 32 : rid = store->table_api.column_find_row(tr, find_sql_column(sysschema, "id"), &id, NULL);
5663 32 : assert(!is_oid_nil(rid));
5664 32 : if ((res = store->table_api.column_update_value(tr, find_sql_column(sysschema, "authorization"), rid, &auth_id)))
5665 : return res;
5666 :
5667 32 : if (!isNew(s) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
5668 : return res;
5669 : /* delete schema, add schema */
5670 32 : if ((res = os_del(tr->cat->schemas, tr, s->base.name, dup_base(&s->base))))
5671 : return res;
5672 32 : if ((res = schema_dup(tr, s, s->base.name, &ns)) || (res = os_add(tr->cat->schemas, tr, ns->base.name, &ns->base))) {
5673 0 : return res;
5674 : }
5675 : return res;
5676 : }
5677 :
5678 : int
5679 161 : sql_trans_drop_schema(sql_trans *tr, sqlid id, int drop_action)
5680 : {
5681 161 : sqlstore *store = tr->store;
5682 161 : sql_schema *s = find_sql_schema_id(tr, id);
5683 161 : sql_table *sysschema = find_sql_table(tr, find_sql_schema(tr, "sys"), "schemas");
5684 161 : oid rid = store->table_api.column_find_row(tr, find_sql_column(sysschema, "id"), &s->base.id, NULL);
5685 161 : int res = LOG_OK;
5686 :
5687 161 : if (is_oid_nil(rid))
5688 : return 0;
5689 161 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
5690 81 : sqlid* local_id = MNEW(sqlid);
5691 81 : if (!local_id)
5692 : return -1;
5693 :
5694 81 : if (!tr->dropped) {
5695 81 : tr->dropped = list_create((fdestroy) &id_destroy);
5696 81 : if (!tr->dropped) {
5697 0 : _DELETE(local_id);
5698 0 : return -1;
5699 : }
5700 : }
5701 81 : *local_id = s->base.id;
5702 81 : list_append(tr->dropped, local_id);
5703 : }
5704 :
5705 161 : if ((res = store->table_api.table_delete(tr, sysschema, rid)))
5706 : return res;
5707 161 : if (!isNew(s) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
5708 : return res;
5709 161 : if ((res = sys_drop_funcs(tr, s, drop_action)))
5710 : return res;
5711 161 : if ((res = sys_drop_tables(tr, s, drop_action)))
5712 : return res;
5713 161 : if ((res = sys_drop_types(tr, s, drop_action)))
5714 : return res;
5715 161 : if ((res = sys_drop_sequences(tr, s, drop_action)))
5716 : return res;
5717 161 : if ((res = sql_trans_drop_any_comment(tr, s->base.id)))
5718 : return res;
5719 161 : if ((res = sql_trans_drop_obj_priv(tr, s->base.id)))
5720 : return res;
5721 :
5722 161 : if ((res = os_del(tr->cat->schemas, tr, s->base.name, dup_base(&s->base))))
5723 : return res;
5724 :
5725 161 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
5726 81 : list_destroy(tr->dropped);
5727 81 : tr->dropped = NULL;
5728 : }
5729 : return res;
5730 : }
5731 :
5732 : static int
5733 495 : sql_trans_propagate_dependencies_parents(sql_trans *tr, sql_table *mt, bool *child_of_partitioned)
5734 : {
5735 495 : int res = LOG_OK;
5736 495 : sql_part *pt = NULL;
5737 :
5738 1020 : for (; mt; mt = pt?pt->t:NULL) {
5739 510 : if ((res = store_reset_sql_functions(tr, mt->base.id))) /* reset sql functions depending on the table */
5740 0 : return res;
5741 510 : if (!isNew(mt) && (res = sql_trans_add_dependency(tr, mt->base.id, ddl))) /* protect from another transaction changing the table's schema */
5742 0 : return res;
5743 510 : if (child_of_partitioned)
5744 620 : *child_of_partitioned |= (isRangePartitionTable(mt) || isListPartitionTable(mt));
5745 510 : pt = partition_find_part(tr, mt, NULL);
5746 : }
5747 : return res;
5748 : }
5749 :
5750 : static int
5751 514 : sql_trans_propagate_dependencies_children(sql_trans *tr, sql_table *pt, bool child_of_partitioned)
5752 : {
5753 514 : int res = LOG_OK;
5754 :
5755 514 : if (THRhighwater()) /* for now throw malloc failure error */
5756 : return -1;
5757 :
5758 514 : if ((res = store_reset_sql_functions(tr, pt->base.id))) /* reset sql functions depending on the table */
5759 : return res;
5760 514 : if (!isNew(pt)) {
5761 354 : if ((res = sql_trans_add_dependency(tr, pt->base.id, ddl))) /* protect from another transaction changing the table's schema */
5762 : return res;
5763 354 : if ((res = sql_trans_add_dependency_change(tr, pt->base.id, ddl))) /* protect from being added twice */
5764 : return res;
5765 354 : if (child_of_partitioned && isTable(pt) && (res = sql_trans_add_dependency(tr, pt->base.id, dml))) /* disallow concurrent updates on pt */
5766 : return res;
5767 : }
5768 514 : if ((isMergeTable(pt) || isReplicaTable(pt)) && !list_empty(pt->members)) {
5769 33 : for (node *nt = pt->members->h; nt; nt = nt->next) {
5770 19 : sql_part *pd = nt->data;
5771 19 : sql_table *t = find_sql_table_id(tr, pt->s, pd->member);
5772 :
5773 19 : child_of_partitioned |= (isRangePartitionTable(t) || isListPartitionTable(t));
5774 19 : if ((res = sql_trans_propagate_dependencies_children(tr, t, child_of_partitioned)))
5775 0 : return res;
5776 : }
5777 : }
5778 : return res;
5779 : }
5780 :
5781 : int
5782 302 : sql_trans_add_table(sql_trans *tr, sql_table *mt, sql_table *pt)
5783 : {
5784 302 : sqlstore *store = tr->store;
5785 302 : sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
5786 302 : sql_table *sysobj = find_sql_table(tr, syss, "objects");
5787 302 : int res = LOG_OK;
5788 302 : sql_table *dup = NULL;
5789 302 : bool child_of_partitioned = false;
5790 :
5791 : /* merge table depends on part table */
5792 302 : if ((res = sql_trans_create_dependency(tr, pt->base.id, mt->base.id, TABLE_DEPENDENCY)))
5793 : return res;
5794 302 : assert(isMergeTable(mt) || isReplicaTable(mt));
5795 :
5796 302 : if ((res = new_table(tr, mt, &dup)))
5797 : return res;
5798 299 : mt = dup;
5799 299 : if (!mt->members)
5800 0 : mt->members = list_create((fdestroy) &part_destroy);
5801 299 : sql_part *p = ZNEW(sql_part);
5802 299 : p->t = mt;
5803 299 : p->member = pt->base.id;
5804 :
5805 299 : base_init(NULL, &p->base, next_oid(store), true, pt->base.name);
5806 299 : list_append(mt->members, p);
5807 299 : if ((res = store->table_api.table_insert(tr, sysobj, &p->base.id, &p->base.name, &mt->base.id, &pt->base.id)))
5808 : return res;
5809 299 : if ((res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
5810 : return res;
5811 299 : if ((res = sql_trans_propagate_dependencies_parents(tr, mt, &child_of_partitioned)))
5812 : return res;
5813 299 : if ((res = sql_trans_propagate_dependencies_children(tr, pt, child_of_partitioned)))
5814 : return res;
5815 : return res;
5816 : }
5817 :
5818 : int
5819 186 : sql_trans_add_range_partition(sql_trans *tr, sql_table *mt, sql_table *pt, sql_subtype tpe, ptr min, ptr max,
5820 : bit with_nills, int update, sql_part **err)
5821 : {
5822 186 : sqlstore *store = tr->store;
5823 186 : sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
5824 186 : sql_table *sysobj = find_sql_table(tr, syss, "objects");
5825 186 : sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
5826 186 : sql_table *ranges = find_sql_table(tr, syss, "range_partitions");
5827 186 : sql_part *p;
5828 186 : int localtype = tpe.type->localtype, res = LOG_OK;
5829 186 : ValRecord vmin, vmax;
5830 186 : size_t smin, smax;
5831 186 : bit to_insert = with_nills;
5832 186 : oid rid;
5833 186 : ptr ok;
5834 186 : sql_table *dup = NULL;
5835 :
5836 186 : assert(sysobj);
5837 186 : assert(partitions);
5838 186 : assert(ranges);
5839 :
5840 186 : vmin = vmax = (ValRecord) {.vtype = TYPE_void,};
5841 :
5842 186 : if ((res = new_table(tr, mt, &dup)))
5843 : return res;
5844 185 : mt = dup;
5845 185 : if (!mt->members)
5846 0 : mt->members = list_create((fdestroy) &part_destroy);
5847 185 : if (min) {
5848 185 : ok = VALinit(&vmin, localtype, min);
5849 185 : if (ok && localtype != TYPE_str)
5850 168 : ok = VALconvert(TYPE_str, &vmin);
5851 : } else {
5852 0 : ok = VALinit(&vmin, TYPE_str, ATOMnilptr(TYPE_str));
5853 0 : min = (ptr) ATOMnilptr(localtype);
5854 : }
5855 185 : if (!ok) {
5856 0 : res = -1;
5857 0 : goto finish;
5858 : }
5859 185 : smin = ATOMlen(localtype, min);
5860 185 : if (smin > STORAGE_MAX_VALUE_LENGTH) {
5861 0 : res = -10;
5862 0 : goto finish;
5863 : }
5864 :
5865 185 : if (max) {
5866 185 : ok = VALinit(&vmax, localtype, max);
5867 185 : if (ok && localtype != TYPE_str)
5868 168 : ok = VALconvert(TYPE_str, &vmax);
5869 : } else {
5870 0 : ok = VALinit(&vmax, TYPE_str, ATOMnilptr(TYPE_str));
5871 0 : max = (ptr) ATOMnilptr(localtype);
5872 : }
5873 185 : if (!ok) {
5874 0 : res = -1;
5875 0 : goto finish;
5876 : }
5877 185 : smax = ATOMlen(localtype, max);
5878 185 : if (smax > STORAGE_MAX_VALUE_LENGTH) {
5879 0 : res = -11;
5880 0 : goto finish;
5881 : }
5882 :
5883 185 : if (!update) {
5884 182 : p = ZNEW(sql_part);
5885 182 : base_init(NULL, &p->base, next_oid(store), true, pt->base.name);
5886 182 : assert(isMergeTable(mt) || isReplicaTable(mt));
5887 182 : p->t = mt;
5888 182 : assert(pt);
5889 182 : p->member = pt->base.id;
5890 : } else {
5891 3 : node *n = members_find_child_id(mt->members, pt->base.id);
5892 3 : p = (sql_part*) n->data;
5893 : }
5894 :
5895 : /* add range partition values */
5896 185 : if (update) {
5897 3 : _DELETE(p->part.range.minvalue);
5898 3 : _DELETE(p->part.range.maxvalue);
5899 : }
5900 185 : p->part.range.minvalue = NEW_ARRAY(char, smin);
5901 185 : p->part.range.maxvalue = NEW_ARRAY(char, smax);
5902 185 : memcpy(p->part.range.minvalue, min, smin);
5903 185 : memcpy(p->part.range.maxvalue, max, smax);
5904 185 : p->part.range.minlength = smin;
5905 185 : p->part.range.maxlength = smax;
5906 185 : p->with_nills = with_nills;
5907 :
5908 185 : if (!update) {
5909 182 : *err = list_append_with_validate(mt->members, p, &localtype, sql_range_part_validate_and_insert);
5910 182 : if (*err)
5911 38 : part_destroy(store, p);
5912 : } else {
5913 3 : *err = list_transverse_with_validate(mt->members, p, &localtype, sql_range_part_validate_and_insert);
5914 : }
5915 185 : if (*err) {
5916 38 : res = -12;
5917 38 : goto finish;
5918 : }
5919 :
5920 147 : if (isPartitionedByColumnTable(p->t))
5921 124 : col_set_range(tr, p, true);
5922 :
5923 147 : if (!update) {
5924 144 : rid = store->table_api.column_find_row(tr, find_sql_column(partitions, "table_id"), &mt->base.id, NULL);
5925 144 : assert(!is_oid_nil(rid));
5926 :
5927 : /* add merge table dependency */
5928 144 : if ((res = sql_trans_create_dependency(tr, pt->base.id, mt->base.id, TABLE_DEPENDENCY)))
5929 0 : goto finish;
5930 144 : sqlid id = store->table_api.column_find_sqlid(tr, find_sql_column(partitions, "id"), rid);
5931 144 : if ((res = store->table_api.table_insert(tr, sysobj, &p->base.id, &p->base.name, &mt->base.id, &pt->base.id)))
5932 0 : goto finish;
5933 144 : char *vmin_val = VALget(&vmin);
5934 144 : char *vmax_val = VALget(&vmax);
5935 144 : if ((res = store->table_api.table_insert(tr, ranges, &pt->base.id, &id, &vmin_val, &vmax_val, &to_insert)))
5936 0 : goto finish;
5937 : } else {
5938 3 : sql_column *cmin = find_sql_column(ranges, "minimum"), *cmax = find_sql_column(ranges, "maximum"),
5939 3 : *wnulls = find_sql_column(ranges, "with_nulls");
5940 :
5941 3 : rid = store->table_api.column_find_row(tr, find_sql_column(ranges, "table_id"), &pt->base.id, NULL);
5942 3 : assert(!is_oid_nil(rid));
5943 :
5944 3 : if ((res = store->table_api.column_update_value(tr, cmin, rid, VALget(&vmin))))
5945 0 : goto finish;
5946 3 : if ((res = store->table_api.column_update_value(tr, cmax, rid, VALget(&vmax))))
5947 0 : goto finish;
5948 3 : if ((res = store->table_api.column_update_value(tr, wnulls, rid, &to_insert)))
5949 0 : goto finish;
5950 : }
5951 :
5952 147 : if (!update && (res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
5953 0 : goto finish;
5954 147 : if ((res = sql_trans_propagate_dependencies_parents(tr, mt, NULL)))
5955 0 : goto finish;
5956 147 : res = sql_trans_propagate_dependencies_children(tr, pt, true);
5957 :
5958 185 : finish:
5959 185 : VALclear(&vmin);
5960 185 : VALclear(&vmax);
5961 185 : return res;
5962 : }
5963 :
5964 : int
5965 54 : sql_trans_add_value_partition(sql_trans *tr, sql_table *mt, sql_table *pt, sql_subtype tpe, list* vals, bit with_nills,
5966 : int update, sql_part **err)
5967 : {
5968 54 : sqlstore *store = tr->store;
5969 54 : sql_schema *syss = find_sql_schema(tr, isGlobal(mt)?"sys":"tmp");
5970 54 : sql_table *sysobj = find_sql_table(tr, syss, "objects");
5971 54 : sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
5972 54 : sql_table *values = find_sql_table(tr, syss, "value_partitions");
5973 54 : sql_part *p;
5974 54 : oid rid;
5975 54 : int localtype = tpe.type->localtype, i = 0, res = LOG_OK;
5976 54 : sql_table *dup = NULL;
5977 :
5978 54 : assert(sysobj);
5979 54 : assert(partitions);
5980 54 : assert(values);
5981 :
5982 54 : if ((res = new_table(tr, mt, &dup)))
5983 : return res;
5984 54 : mt = dup;
5985 54 : if (!mt->members)
5986 0 : mt->members = list_create((fdestroy) &part_destroy);
5987 54 : if (!update) {
5988 52 : p = ZNEW(sql_part);
5989 52 : base_init(NULL, &p->base, next_oid(store), true, pt->base.name);
5990 52 : assert(isMergeTable(mt) || isReplicaTable(mt));
5991 52 : p->t = mt;
5992 52 : assert(pt);
5993 52 : p->member = pt->base.id;
5994 : } else {
5995 2 : rids *rs;
5996 2 : node *n = members_find_child_id(mt->members, pt->base.id);
5997 2 : p = (sql_part*) n->data;
5998 :
5999 2 : rs = store->table_api.rids_select(tr, find_sql_column(values, "table_id"), &pt->base.id, &pt->base.id, NULL);
6000 2 : if (rs == NULL)
6001 : return LOG_ERR;
6002 8 : for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
6003 6 : if ((res = store->table_api.table_delete(tr, values, rid))) { /* eliminate the old values */
6004 0 : store->table_api.rids_destroy(rs);
6005 0 : return res;
6006 : }
6007 : }
6008 2 : store->table_api.rids_destroy(rs);
6009 : }
6010 54 : p->with_nills = with_nills;
6011 :
6012 54 : rid = store->table_api.column_find_row(tr, find_sql_column(partitions, "table_id"), &mt->base.id, NULL);
6013 54 : assert(!is_oid_nil(rid));
6014 :
6015 54 : sqlid id = store->table_api.column_find_sqlid(tr, find_sql_column(partitions, "id"), rid);
6016 :
6017 54 : if (with_nills) { /* store the null value first */
6018 11 : ValRecord vnnil;
6019 11 : if (VALinit(&vnnil, TYPE_str, ATOMnilptr(TYPE_str)) == NULL) {
6020 0 : if (!update)
6021 0 : part_destroy(store, p);
6022 0 : list_destroy2(vals, store);
6023 0 : return -1;
6024 : }
6025 11 : char *vnnil_val = VALget(&vnnil);
6026 11 : if ((res = store->table_api.table_insert(tr, values, &pt->base.id, &id, &vnnil_val))) {
6027 0 : list_destroy2(vals, store);
6028 0 : return res;
6029 : }
6030 11 : VALclear(&vnnil);
6031 : }
6032 :
6033 217 : for (node *n = vals->h ; n ; n = n->next) {
6034 163 : sql_part_value *next = (sql_part_value*) n->data;
6035 163 : ValRecord vvalue;
6036 163 : ptr ok;
6037 :
6038 163 : if (ATOMlen(localtype, next->value) > STORAGE_MAX_VALUE_LENGTH) {
6039 0 : if (!update)
6040 0 : part_destroy(store, p);
6041 0 : list_destroy2(vals, store);
6042 0 : return -i - 10;
6043 : }
6044 163 : ok = VALinit(&vvalue, localtype, next->value);
6045 163 : if (ok && localtype != TYPE_str)
6046 163 : ok = VALconvert(TYPE_str, &vvalue);
6047 163 : if (!ok) {
6048 0 : if (!update)
6049 0 : part_destroy(store, p);
6050 0 : VALclear(&vvalue);
6051 0 : list_destroy2(vals, store);
6052 0 : return -i - 10;
6053 : }
6054 163 : char *vvalue_val = VALget(&vvalue);
6055 163 : if ((res = store->table_api.table_insert(tr, values, &pt->base.id, &id, &vvalue_val))) {
6056 0 : VALclear(&vvalue);
6057 0 : list_destroy2(vals, store);
6058 0 : return res;
6059 : }
6060 :
6061 163 : VALclear(&vvalue);
6062 163 : i++;
6063 : }
6064 :
6065 54 : if (p->part.values)
6066 2 : list_destroy2(p->part.values, store);
6067 54 : p->part.values = vals;
6068 :
6069 54 : if (!update) {
6070 52 : *err = list_append_with_validate(mt->members, p, &localtype, sql_values_part_validate_and_insert);
6071 52 : if (*err)
6072 5 : part_destroy(store, p);
6073 : } else {
6074 2 : *err = list_transverse_with_validate(mt->members, p, &localtype, sql_values_part_validate_and_insert);
6075 : }
6076 54 : if (*err)
6077 : return -4;
6078 :
6079 49 : if (!update) {
6080 : /* add merge table dependency */
6081 47 : if ((res = sql_trans_create_dependency(tr, pt->base.id, mt->base.id, TABLE_DEPENDENCY)))
6082 : return res;
6083 47 : if ((res = store->table_api.table_insert(tr, sysobj, &p->base.id, &p->base.name, &mt->base.id, &pt->base.id)))
6084 : return res;
6085 47 : if ((res = os_add(mt->s->parts, tr, p->base.name, dup_base(&p->base))))
6086 : return res;
6087 : }
6088 49 : if ((res = sql_trans_propagate_dependencies_parents(tr, mt, NULL)))
6089 : return res;
6090 49 : if ((res = sql_trans_propagate_dependencies_children(tr, pt, true)))
6091 : return res;
6092 : return res;
6093 : }
6094 :
6095 : int
6096 19 : sql_trans_rename_table(sql_trans *tr, sql_schema *s, sqlid id, const char *new_name)
6097 : {
6098 19 : sqlstore *store = tr->store;
6099 37 : sql_table *systable = find_sql_table(tr, find_sql_schema(tr, isTempSchema(s) ? "tmp":"sys"), "_tables");
6100 19 : sql_table *t = find_sql_table_id(tr, s, id), *dup = NULL;
6101 19 : oid rid;
6102 19 : int res = LOG_OK;
6103 :
6104 38 : assert(!strNil(new_name));
6105 :
6106 19 : rid = store->table_api.column_find_row(tr, find_sql_column(systable, "id"), &id, NULL);
6107 19 : assert(!is_oid_nil(rid));
6108 19 : if ((res = store->table_api.column_update_value(tr, find_sql_column(systable, "name"), rid, (void*) new_name)))
6109 : return res;
6110 :
6111 17 : if (isGlobal(t)) {
6112 16 : if (!isNew(t) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
6113 : return res;
6114 16 : if ((res = os_del(s->tables, tr, t->base.name, dup_base(&t->base))))
6115 : return res;
6116 : } else {
6117 1 : assert(isTempTable(t));
6118 1 : sql_base *b = os_find_id(tr->localtmps, tr, t->base.id);
6119 1 : if ((res = os_del(tr->localtmps, tr, b->name, dup_base(b))))
6120 : return res;
6121 : }
6122 :
6123 16 : if ((res = table_dup(tr, t, t->s, new_name, &dup, true)))
6124 : return res;
6125 : return res;
6126 : }
6127 :
6128 : int
6129 26 : sql_trans_set_table_schema(sql_trans *tr, sqlid id, sql_schema *os, sql_schema *ns)
6130 : {
6131 26 : sqlstore *store = tr->store;
6132 52 : sql_table *systable = find_sql_table(tr, find_sql_schema(tr, isTempSchema(os) ? "tmp":"sys"), "_tables");
6133 26 : sql_base *b = os_find_id(os->tables, tr, id);
6134 26 : sql_table *t = (sql_table*)b, *dup = NULL;
6135 26 : oid rid;
6136 26 : int res = LOG_OK;
6137 :
6138 26 : rid = store->table_api.column_find_row(tr, find_sql_column(systable, "id"), &t->base.id, NULL);
6139 26 : assert(!is_oid_nil(rid));
6140 26 : if ((res = store->table_api.column_update_value(tr, find_sql_column(systable, "schema_id"), rid, &(ns->base.id))))
6141 : return res;
6142 :
6143 26 : if (!isNew(t) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
6144 : return res;
6145 26 : if ((res = os_del(os->tables, tr, t->base.name, dup_base(&t->base))))
6146 : return res;
6147 25 : return table_dup(tr, t, ns, NULL, &dup, true);
6148 : }
6149 :
6150 : int
6151 191 : sql_trans_del_table(sql_trans *tr, sql_table *mt, sql_table *pt, int drop_action)
6152 : {
6153 191 : int res = LOG_OK;
6154 191 : sqlstore *store = tr->store;
6155 191 : sql_table *dup = NULL, *mt_it;
6156 191 : sql_part *mti_part = NULL;
6157 :
6158 191 : if ((res = new_table(tr, mt, &dup)))
6159 : return res;
6160 191 : mt = dup;
6161 191 : node *n = members_find_child_id(mt->members, pt->base.id); /* get sqlpart id*/
6162 191 : sqlid part_id = ((sql_part*)n->data)->base.id;
6163 191 : sql_base *b = os_find_id(mt->s->parts, tr, part_id); /* fetch updated part */
6164 191 : sql_part *p = (sql_part*)b;
6165 :
6166 191 : if ((res = sys_drop_part(tr, p, drop_action)))
6167 : return res;
6168 : /*Clean the part from members*/
6169 191 : list_remove_node(mt->members, store, n);
6170 :
6171 191 : if (drop_action == DROP_CASCADE && (res = sql_trans_drop_table_id(tr, mt->s, pt->base.id, drop_action)))
6172 : return res;
6173 406 : for (mt_it = mt; mt_it; mt_it = mti_part?mti_part->t:NULL) {
6174 : /* functions depending on parent tables need to be recompiled, ugh */
6175 203 : if ((res = store_reset_sql_functions(tr, mt_it->base.id))) /* reset sql functions depending on the table */
6176 0 : return res;
6177 203 : mti_part = partition_find_part(tr, mt_it, NULL);
6178 : }
6179 191 : if ((res = store_reset_sql_functions(tr, pt->base.id))) /* reset sql functions depending on the table */
6180 : return res;
6181 : return res;
6182 : }
6183 :
6184 : int
6185 35169 : sql_trans_create_table(sql_table **tres, sql_trans *tr, sql_schema *s, const char *name, const char *sql, int tt, bit system,
6186 : int persistence, int commit_action, int sz, bte properties)
6187 : {
6188 35169 : sqlstore *store = tr->store;
6189 35169 : sql_table *t = create_sql_table_with_id(NULL, next_oid(tr->store), name, tt, system, persistence, commit_action, properties);
6190 35246 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
6191 35169 : sql_table *systable = find_sql_table(tr, syss, "_tables");
6192 35169 : sht ca;
6193 35169 : int res = LOG_OK;
6194 :
6195 : /* temps all belong to a special tmp schema and only views/remote have a query */
6196 35169 : assert( (isTable(t) ||
6197 : (!isTempTable(t) || (strcmp(s->base.name, "tmp") == 0) || isDeclaredTable(t))) || (isView(t) && !sql) || (isRemote(t) && !sql));
6198 :
6199 35169 : t->query = sql ?_STRDUP(sql) : NULL;
6200 35169 : t->s = s;
6201 35169 : t->sz = sz;
6202 35169 : if (sz < 0)
6203 1380 : t->sz = COLSIZE;
6204 :
6205 35169 : if ((res = os_add(isGlobal(t)?s->tables:tr->localtmps, tr, t->base.name, &t->base)))
6206 : return res;
6207 :
6208 35165 : if (isUnloggedTable(t))
6209 6 : t->persistence = SQL_PERSIST; // It's not a temporary
6210 :
6211 35165 : if (isRemote(t))
6212 101 : t->persistence = SQL_REMOTE;
6213 :
6214 35165 : if (isTable(t))
6215 11268 : if ((res = store->storage_api.create_del(tr, t))) {
6216 : return res;
6217 : }
6218 35165 : if (isPartitionedByExpressionTable(t)) {
6219 27 : t->part.pexp = ZNEW(sql_expression);
6220 27 : t->part.pexp->type = *sql_bind_localtype("void"); /* leave it non-initialized, at the backend the copy of this table will get the type */
6221 27 : t->part.pexp->cols = list_create((fdestroy) &int_destroy);
6222 : }
6223 :
6224 35165 : ca = t->commit_action;
6225 35165 : if (!isDeclaredTable(t)) {
6226 35165 : char *strnil = (char*)ATOMnilptr(TYPE_str);
6227 35165 : if ((res = store->table_api.table_insert(tr, systable, &t->base.id, &t->base.name, &s->base.id,
6228 35165 : (t->query) ? &t->query : &strnil, &t->type, &t->system, &ca, &t->access))) {
6229 0 : return res;
6230 : }
6231 : }
6232 35165 : *tres = t;
6233 35165 : return res;
6234 : }
6235 :
6236 : int
6237 34638 : sql_trans_set_partition_table(sql_trans *tr, sql_table *t)
6238 : {
6239 34638 : int res = LOG_OK;
6240 34638 : sqlstore *store = tr->store;
6241 :
6242 34638 : if (t && (isRangePartitionTable(t) || isListPartitionTable(t))) {
6243 104 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
6244 104 : sql_table *partitions = find_sql_table(tr, syss, "table_partitions");
6245 104 : assert(partitions);
6246 104 : sqlid next = next_oid(tr->store);
6247 104 : if (isPartitionedByColumnTable(t)) {
6248 80 : assert(t->part.pcol);
6249 80 : if ((res = store->table_api.table_insert(tr, partitions, &next, &t->base.id, &t->part.pcol->base.id, &ATOMnilptr(TYPE_str), &t->properties)))
6250 0 : return res;
6251 24 : } else if (isPartitionedByExpressionTable(t)) {
6252 24 : assert(t->part.pexp->exp);
6253 24 : if (strlen(t->part.pexp->exp) > STORAGE_MAX_VALUE_LENGTH)
6254 : return -4;
6255 24 : if ((res = store->table_api.table_insert(tr, partitions, &next, &t->base.id, ATOMnilptr(TYPE_int), &t->part.pexp->exp, &t->properties)))
6256 : return res;
6257 : } else {
6258 0 : assert(0);
6259 : }
6260 : }
6261 : return res;
6262 : }
6263 :
6264 : sql_key *
6265 7643 : create_sql_kc(sqlstore *store, allocator *sa, sql_key *k, sql_column *c)
6266 : {
6267 7643 : sql_kc *kc = SA_ZNEW(sa, sql_kc);
6268 :
6269 7643 : kc->c = c;
6270 7643 : list_append(k->columns, kc);
6271 7643 : if (k->idx)
6272 962 : create_sql_ic(store, sa, k->idx, c);
6273 7643 : if (k->type == pkey)
6274 4256 : c->null = 0;
6275 7643 : return k;
6276 : }
6277 :
6278 : sql_key *
6279 6070 : create_sql_ukey(sqlstore *store, allocator *sa, sql_table *t, const char *name, key_type kt, const char* check)
6280 : {
6281 6070 : sql_key *nk = NULL;
6282 6070 : sql_ukey *tk;
6283 :
6284 6070 : nk = (kt != fkey) ? (sql_key *) SA_ZNEW(sa, sql_ukey) : (sql_key *) SA_ZNEW(sa, sql_fkey);
6285 6070 : tk = (sql_ukey *) nk;
6286 6070 : assert(name);
6287 :
6288 6070 : base_init(sa, &nk->base, next_oid(store), true, name);
6289 6070 : nk->type = kt;
6290 6070 : nk->columns = SA_LIST(sa, (fdestroy) NULL);
6291 6070 : nk->idx = NULL;
6292 6070 : nk->t = t;
6293 6070 : nk->check = check ? SA_STRDUP(sa, check) : NULL;
6294 :
6295 6070 : if (nk->type == pkey)
6296 3937 : t->pkey = tk;
6297 6070 : if (ol_add(t->keys, &nk->base))
6298 0 : return NULL;
6299 : return nk;
6300 : }
6301 :
6302 : sql_fkey *
6303 941 : create_sql_fkey(sqlstore *store, allocator *sa, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update)
6304 : {
6305 941 : sql_key *nk;
6306 941 : sql_fkey *fk = NULL;
6307 :
6308 941 : nk = (kt != fkey) ? (sql_key *) SA_ZNEW(sa, sql_ukey) : (sql_key *) SA_ZNEW(sa, sql_fkey);
6309 :
6310 941 : assert(name);
6311 941 : base_init(sa, &nk->base, next_oid(store), true, name);
6312 941 : nk->type = kt;
6313 941 : nk->columns = SA_LIST(sa, (fdestroy) NULL);
6314 941 : nk->t = t;
6315 941 : nk->idx = create_sql_idx(store, sa, t, name, (nk->type == fkey) ? join_idx : hash_idx);
6316 941 : nk->idx->key = nk;
6317 :
6318 941 : fk = (sql_fkey *) nk;
6319 :
6320 941 : fk->on_delete = on_delete;
6321 941 : fk->on_update = on_update;
6322 :
6323 941 : fk->rkey = rkey->base.id;
6324 941 : if (ol_add(t->keys, &nk->base))
6325 0 : return NULL;
6326 : return (sql_fkey*) nk;
6327 : }
6328 :
6329 : sql_idx *
6330 7310 : create_sql_idx(sqlstore *store, allocator *sa, sql_table *t, const char *name, idx_type it)
6331 : {
6332 7310 : sql_idx *ni = SA_ZNEW(sa, sql_idx);
6333 :
6334 7310 : base_init(sa, &ni->base, next_oid(store), true, name);
6335 7310 : ni->columns = SA_LIST(sa, (fdestroy) NULL);
6336 7310 : ni->t = t;
6337 7310 : ni->type = it;
6338 7310 : ni->key = NULL;
6339 7310 : if (ol_add(t->idxs, &ni->base))
6340 0 : return NULL;
6341 : return ni;
6342 : }
6343 :
6344 : sql_idx *
6345 8038 : create_sql_ic(sqlstore *store, allocator *sa, sql_idx *i, sql_column *c)
6346 : {
6347 8038 : sql_kc *ic = SA_ZNEW(sa, sql_kc);
6348 :
6349 8038 : ic->c = c;
6350 8038 : list_append(i->columns, ic);
6351 :
6352 8038 : (void)store;
6353 8038 : return i;
6354 : }
6355 :
6356 : sql_idx *
6357 10051 : create_sql_idx_done(sql_trans *tr, sql_idx *i)
6358 : {
6359 10051 : (void) tr;
6360 10051 : if (i && i->key && hash_index(i->type)) {
6361 8688 : int ncols = list_length(i->columns);
6362 18012 : for (node *n = i->columns->h ; n ; n = n->next) {
6363 9324 : sql_kc *kc = n->data;
6364 :
6365 9324 : kc->c->unique = (ncols == 1) ? 2 : MAX(kc->c->unique, 1);
6366 : }
6367 : }
6368 10051 : return i;
6369 : }
6370 :
6371 : sql_column *
6372 262898 : create_sql_column(sqlstore *store, allocator *sa, sql_table *t, const char *name, sql_subtype *tpe)
6373 : {
6374 262898 : return create_sql_column_with_id(sa, next_oid(store), t, name, tpe, column_plain);
6375 : }
6376 :
6377 : int
6378 4350 : sql_trans_drop_table(sql_trans *tr, sql_schema *s, const char *name, int drop_action)
6379 : {
6380 4350 : sql_table *t = find_sql_table(tr, s, name);
6381 :
6382 4350 : if (!t) {
6383 0 : TRC_ERROR(SQL_STORE, "sql_trans_drop_table: Table %s.%s does not exist\n", s->base.name, name);
6384 0 : return -1;
6385 : }
6386 :
6387 4350 : sql_table *gt = t;
6388 4350 : if (t && isTempTable(t)) {
6389 116 : gt = (sql_table*)os_find_id(s->tables, tr, t->base.id);
6390 : }
6391 :
6392 4350 : assert(t == gt || !gt || (isTempTable(gt) && !isLocalTemp(gt) && isLocalTemp(t)));
6393 :
6394 4350 : int res = LOG_OK;
6395 :
6396 4350 : if ((drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) &&
6397 767 : tr->dropped && list_find_id(tr->dropped, t->base.id))
6398 : return res;
6399 :
6400 767 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
6401 767 : sqlid *local_id = MNEW(sqlid);
6402 767 : if (!local_id)
6403 : return -1;
6404 :
6405 767 : if (! tr->dropped) {
6406 687 : tr->dropped = list_create((fdestroy) &id_destroy);
6407 687 : if (!tr->dropped) {
6408 0 : _DELETE(local_id);
6409 0 : return -1;
6410 : }
6411 : }
6412 767 : *local_id = t->base.id;
6413 767 : list_append(tr->dropped, local_id);
6414 : }
6415 :
6416 4350 : if (!isDeclaredTable(t))
6417 4405 : if ((res = sys_drop_table(tr, gt?gt:t, drop_action)))
6418 : return res;
6419 :
6420 4350 : if (isNew(t))
6421 219 : t->base.deleted = 1;
6422 4350 : if (gt && (res = os_del(s->tables, tr, gt->base.name, dup_base(>->base))))
6423 : return res;
6424 4350 : if (t != gt && (res = os_del(tr->localtmps, tr, t->base.name, dup_base(&t->base))))
6425 : return res;
6426 :
6427 4350 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
6428 687 : list_destroy(tr->dropped);
6429 687 : tr->dropped = NULL;
6430 : }
6431 : return res;
6432 : }
6433 :
6434 : int
6435 64 : sql_trans_drop_table_id(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
6436 : {
6437 64 : sql_table *t = find_sql_table_id(tr, s, id);
6438 :
6439 64 : if (t)
6440 64 : return sql_trans_drop_table(tr, s, t->base.name, drop_action);
6441 : else
6442 : return SQL_ERR;
6443 : }
6444 :
6445 : BUN
6446 41806 : sql_trans_clear_table(sql_trans *tr, sql_table *t)
6447 : {
6448 41806 : sqlstore *store = tr->store;
6449 41806 : return store->storage_api.clear_table(tr, t);
6450 : }
6451 :
6452 : int
6453 10194 : sql_trans_create_column(sql_column **rcol, sql_trans *tr, sql_table *t, const char *name, sql_subtype *tpe)
6454 : {
6455 10194 : return sql_trans_create_column_intern(rcol, tr, t, name, tpe, column_plain);
6456 : }
6457 :
6458 : void
6459 68 : drop_sql_column(sql_table *t, sqlid id, int drop_action)
6460 : {
6461 68 : node *n = ol_find_id(t->columns, id);
6462 68 : sql_column *col = n->data;
6463 :
6464 68 : col->drop_action = drop_action;
6465 68 : col->base.deleted = 1;
6466 : //ol_del(t->columns, t->s->store, n);
6467 68 : }
6468 :
6469 : void
6470 0 : drop_sql_idx(sql_table *t, sqlid id)
6471 : {
6472 0 : node *n = ol_find_id(t->idxs, id);
6473 0 : sql_idx *i = n->data;
6474 :
6475 0 : i->base.deleted = 1;
6476 : //ol_del(t->idxs, t->s->store, n);
6477 0 : }
6478 :
6479 : void
6480 0 : drop_sql_key(sql_table *t, sqlid id, int drop_action)
6481 : {
6482 0 : node *n = ol_find_id(t->keys, id);
6483 0 : sql_key *k = n->data;
6484 :
6485 0 : k->drop_action = drop_action;
6486 0 : k->base.deleted = 1;
6487 : //ol_del(t->keys, t->s->store, n);
6488 0 : }
6489 :
6490 : int
6491 13 : sql_trans_rename_column(sql_trans *tr, sql_table *t, sqlid id, const char *old_name, const char *new_name)
6492 : {
6493 13 : sqlstore *store = tr->store;
6494 13 : sql_table *syscolumn = find_sql_table(tr, find_sql_schema(tr, isGlobal(t)?"sys":"tmp"), "_columns");
6495 13 : oid rid;
6496 13 : int res = LOG_OK;
6497 13 : sql_table *dup = NULL;
6498 13 : node *n;
6499 :
6500 26 : assert(!strNil(new_name));
6501 :
6502 13 : rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"), &id, NULL);
6503 13 : assert(!is_oid_nil(rid));
6504 13 : if ((res = store->table_api.column_update_value(tr, find_sql_column(syscolumn, "name"), rid, (void*) new_name)))
6505 : return res;
6506 :
6507 13 : if ((res = new_table(tr, t, &dup)))
6508 : return res;
6509 13 : t = dup;
6510 13 : if (!(n = ol_find_name(t->columns, old_name)))
6511 : return -1;
6512 13 : sql_column *c = n->data;
6513 :
6514 13 : if (!isNew(c) && (res = sql_trans_add_dependency_change(tr, c->t->base.id, ddl)))
6515 : return res;
6516 13 : if (!isNew(c) && (res = sql_trans_add_dependency_change(tr, id, ddl)))
6517 : return res;
6518 :
6519 13 : _DELETE(c->base.name);
6520 13 : c->base.name =_STRDUP(new_name);
6521 13 : if (ol_rehash(t->columns, old_name, n) == NULL)
6522 : return -1;
6523 : return res;
6524 : }
6525 :
6526 : static int
6527 656 : new_column(sql_trans *tr, sql_column *col, sql_column **cres)
6528 : {
6529 656 : int res = LOG_OK;
6530 656 : sql_table *t = NULL;
6531 :
6532 656 : if ((res = new_table(tr, col->t, &t)))
6533 : return res;
6534 656 : *cres = find_sql_column(t, col->base.name);
6535 656 : return res;
6536 : }
6537 :
6538 : int
6539 71 : sql_trans_drop_column(sql_trans *tr, sql_table *t, sqlid id, int drop_action)
6540 : {
6541 71 : sqlstore *store = tr->store;
6542 71 : node *n = NULL;
6543 71 : sql_table *syscolumn = find_sql_table(tr, find_sql_schema(tr, isGlobal(t)?"sys":"tmp"), "_columns");
6544 71 : sql_column *col = NULL, *cid = find_sql_column(syscolumn, "id"), *cnr = find_sql_column(syscolumn, "number");
6545 71 : int res = LOG_OK;
6546 71 : sql_table *dup = NULL;
6547 :
6548 71 : if ((res = new_table(tr, t, &dup)))
6549 : return res;
6550 70 : t = dup;
6551 70 : t->multiset=false;
6552 70 : t->composite=false;
6553 537 : for (node *nn = t->columns->l->h ; nn ; nn = nn->next) {
6554 467 : sql_column *next = (sql_column *) nn->data;
6555 467 : if (next->base.id == id) {
6556 : n = nn;
6557 : col = next;
6558 397 : } else if (col) { /* if the column to be dropped was found, decrease the column number for others after it */
6559 92 : next->colnr--;
6560 :
6561 92 : if (next->type.multiset)
6562 0 : t->multiset=true;
6563 92 : if (next->type.type->composite)
6564 0 : t->composite=false;
6565 92 : if (!isDeclaredTable(t)) {
6566 92 : oid rid = store->table_api.column_find_row(tr, cid, &next->base.id, NULL);
6567 92 : assert(!is_oid_nil(rid));
6568 92 : if ((res = store->table_api.column_update_value(tr, cnr, rid, &next->colnr)))
6569 0 : return res;
6570 : }
6571 : }
6572 : }
6573 :
6574 70 : assert(n && col); /* the column to be dropped must have been found */
6575 :
6576 70 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
6577 11 : sqlid *local_id = MNEW(sqlid);
6578 11 : if (!local_id)
6579 : return -1;
6580 :
6581 11 : if (! tr->dropped) {
6582 8 : tr->dropped = list_create((fdestroy) &id_destroy);
6583 8 : if (!tr->dropped) {
6584 0 : _DELETE(local_id);
6585 0 : return -1;
6586 : }
6587 : }
6588 11 : *local_id = col->base.id;
6589 11 : list_append(tr->dropped, local_id);
6590 : }
6591 :
6592 70 : if (!isNew(col) && (res = sql_trans_add_dependency_change(tr, col->t->base.id, ddl)))
6593 : return res;
6594 70 : if (!isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml)))
6595 : return res;
6596 70 : if ((res = sys_drop_column(tr, col, drop_action)))
6597 : return res;
6598 :
6599 70 : if (isNew(col)) { /* remove create from changes */
6600 7 : trans_del(tr, &col->base);
6601 7 : if (!isNew(col->t))
6602 1 : column_destroy(store, col);
6603 : }
6604 70 : ol_del(t->columns, store, n);
6605 :
6606 70 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
6607 8 : list_destroy(tr->dropped);
6608 8 : tr->dropped = NULL;
6609 : }
6610 : return res;
6611 : }
6612 :
6613 : int
6614 4790 : sql_trans_alter_null(sql_trans *tr, sql_column *col, int isnull)
6615 : {
6616 4790 : int res = LOG_OK;
6617 4790 : sqlstore *store = tr->store;
6618 :
6619 4790 : if (col->null != isnull) {
6620 575 : sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
6621 575 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
6622 575 : oid rid = store->table_api.column_find_row(tr, find_sql_column(syscolumn, "id"),
6623 575 : &col->base.id, NULL);
6624 575 : sql_column *dup = NULL;
6625 :
6626 575 : if (is_oid_nil(rid))
6627 1 : return -1;
6628 575 : if ((res = store->table_api.column_update_value(tr, find_sql_column(syscolumn, "null"), rid, &isnull)))
6629 : return res;
6630 :
6631 574 : if ((res = new_column(tr, col, &dup)))
6632 : return res;
6633 574 : col = dup;
6634 574 : dup->null = isnull;
6635 :
6636 : /* disallow concurrent updates on the column if not null is set */
6637 : /* this dependency is needed for merge tables */
6638 574 : if (!isNew(col) && (res = sql_trans_add_dependency(tr, col->t->base.id, ddl)))
6639 : return res;
6640 574 : if (!isnull && !isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml)))
6641 : return res;
6642 574 : if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */
6643 : return res;
6644 574 : if (isNew(col) || isnull) /* new ie can still change, or persistent only widen semantics */
6645 469 : store->storage_api.col_not_null(tr, col, !isnull);
6646 : }
6647 : return res;
6648 : }
6649 :
6650 : int
6651 2359 : sql_trans_alter_access(sql_trans *tr, sql_table *t, sht access)
6652 : {
6653 2359 : int res = LOG_OK;
6654 2359 : sqlstore *store = tr->store;
6655 :
6656 2359 : if (t->access != access) {
6657 2359 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
6658 2359 : sql_table *systable = find_sql_table(tr, syss, "_tables");
6659 2359 : oid rid = store->table_api.column_find_row(tr, find_sql_column(systable, "id"),
6660 2359 : &t->base.id, NULL);
6661 2359 : sql_table *dup = NULL;
6662 :
6663 2359 : if (is_oid_nil(rid))
6664 0 : return -1;
6665 2359 : if ((res = store->table_api.column_update_value(tr, find_sql_column(systable, "access"), rid, &access)))
6666 : return res;
6667 2359 : if ((res = new_table(tr, t, &dup)))
6668 : return res;
6669 2359 : t = dup;
6670 2359 : t->access = access;
6671 2359 : if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml)))
6672 : return res;
6673 2359 : if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
6674 : return res;
6675 : }
6676 : return res;
6677 : }
6678 :
6679 : int
6680 23 : sql_trans_alter_default(sql_trans *tr, sql_column *col, char *val)
6681 : {
6682 23 : int res = LOG_OK;
6683 23 : sqlstore *store = tr->store;
6684 :
6685 23 : if ((col->def || val) && (!col->def || !val || strcmp(col->def, val) != 0)) {
6686 19 : void *p = val ? val : (void *) ATOMnilptr(TYPE_str);
6687 23 : sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
6688 23 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
6689 23 : sql_column *col_ids = find_sql_column(syscolumn, "id");
6690 23 : sql_column *col_dfs = find_sql_column(syscolumn, "default");
6691 23 : oid rid = store->table_api.column_find_row(tr, col_ids, &col->base.id, NULL);
6692 23 : sql_column *dup = NULL;
6693 :
6694 23 : if (is_oid_nil(rid))
6695 0 : return -1;
6696 23 : if ((res = sys_drop_default_object(tr, col, 0)))
6697 : return res;
6698 23 : if ((res = store->table_api.column_update_value(tr, col_dfs, rid, p)))
6699 : return res;
6700 :
6701 23 : if ((res = new_column(tr, col, &dup)))
6702 : return res;
6703 23 : _DELETE(dup->def);
6704 23 : if (val)
6705 17 : dup->def =_STRDUP(val);
6706 23 : if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */
6707 : return res;
6708 : }
6709 : return res;
6710 : }
6711 :
6712 : int
6713 59 : sql_trans_alter_storage(sql_trans *tr, sql_column *col, char *storage)
6714 : {
6715 59 : int res = LOG_OK;
6716 59 : sqlstore *store = tr->store;
6717 :
6718 59 : if ((col->storage_type || storage) && (!col->storage_type || !storage || strcmp(col->storage_type, storage) != 0)) {
6719 59 : void *p = storage ? storage : (void *) ATOMnilptr(TYPE_str);
6720 59 : sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp");
6721 59 : sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
6722 59 : sql_column *col_ids = find_sql_column(syscolumn, "id");
6723 59 : sql_column *col_dfs = find_sql_column(syscolumn, "storage");
6724 59 : oid rid = store->table_api.column_find_row(tr, col_ids, &col->base.id, NULL);
6725 59 : sql_column *dup = NULL;
6726 :
6727 59 : if (is_oid_nil(rid))
6728 0 : return -1;
6729 59 : if ((res = store->table_api.column_update_value(tr, col_dfs, rid, p)))
6730 : return res;
6731 :
6732 59 : if ((res = new_column(tr, col, &dup)))
6733 : return res;
6734 59 : _DELETE(dup->storage_type);
6735 59 : if (storage)
6736 58 : dup->storage_type =_STRDUP(storage);
6737 59 : if (!isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml)))
6738 : return res;
6739 59 : if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */
6740 : return res;
6741 : }
6742 : return res;
6743 : }
6744 :
6745 : int
6746 18772 : sql_trans_is_sorted( sql_trans *tr, sql_column *col )
6747 : {
6748 18772 : sqlstore *store = tr->store;
6749 18772 : if (col && isTable(col->t) && store->storage_api.sorted_col && store->storage_api.sorted_col(tr, col))
6750 : return 1;
6751 : return 0;
6752 : }
6753 :
6754 : int
6755 6815 : sql_trans_is_unique( sql_trans *tr, sql_column *col )
6756 : {
6757 6815 : sqlstore *store = tr->store;
6758 6815 : if (col && isTable(col->t) && store->storage_api.unique_col && store->storage_api.unique_col(tr, col))
6759 : return 1;
6760 : return 0;
6761 : }
6762 :
6763 : int
6764 1872 : sql_trans_is_duplicate_eliminated( sql_trans *tr, sql_column *col )
6765 : {
6766 1872 : sqlstore *store = tr->store;
6767 1872 : if (col && isTable(col->t) && store->storage_api.double_elim_col)
6768 1872 : return store->storage_api.double_elim_col(tr, col);
6769 : return 0;
6770 : }
6771 :
6772 : int
6773 4383856 : sql_trans_col_stats( sql_trans *tr, sql_column *col, bool *nonil, bool *unique, double *unique_est, ValPtr min, ValPtr max )
6774 : {
6775 4383856 : sqlstore *store = tr->store;
6776 4383856 : if (col && isTable(col->t) && store->storage_api.col_stats)
6777 4070654 : return store->storage_api.col_stats(tr, col, nonil, unique, unique_est, min, max);
6778 : return 0;
6779 : }
6780 :
6781 : size_t
6782 0 : sql_trans_dist_count( sql_trans *tr, sql_column *col )
6783 : {
6784 0 : sqlstore *store = tr->store;
6785 :
6786 0 : if (col && isTable(col->t)) {
6787 0 : if (!col->dcount)
6788 0 : col->dcount = store->storage_api.dcount_col(tr, col);
6789 0 : return col->dcount;
6790 : }
6791 : return 0;
6792 : }
6793 :
6794 : int
6795 87 : sql_trans_ranges( sql_trans *tr, sql_column *col, void **min, void **max )
6796 : {
6797 87 : sqlstore *store = tr->store;
6798 :
6799 87 : *min = NULL;
6800 87 : *max = NULL;
6801 87 : if (col && isTable(col->t)) {
6802 87 : if (!col->min || !col->max)
6803 19 : (void) store->storage_api.min_max_col(tr, col);
6804 87 : *min = col->min;
6805 87 : *max = col->max;
6806 : }
6807 87 : return *min != NULL && *max != NULL;
6808 : }
6809 :
6810 : int
6811 230 : sql_trans_create_ukey(sql_key **kres, sql_trans *tr, sql_table *t, const char *name, key_type kt, const char* check)
6812 : {
6813 : /* can only have keys between persistent tables */
6814 230 : sqlstore *store = tr->store;
6815 230 : int neg = -1, action = -1, res = LOG_OK;
6816 230 : sql_key *nk;
6817 230 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
6818 230 : sql_table *syskey = find_sql_table(tr, syss, "keys");
6819 230 : sql_ukey *uk = NULL;
6820 230 : sql_table *dup = NULL;
6821 :
6822 230 : if (isTempTable(t))
6823 : return -1; /* TODO not sure here */
6824 :
6825 230 : if ((res = new_table(tr, t, &dup)))
6826 : return res;
6827 230 : t = dup;
6828 230 : nk = (kt != fkey) ? (sql_key *) ZNEW(sql_ukey)
6829 230 : : (sql_key *) ZNEW(sql_fkey);
6830 :
6831 230 : assert(name);
6832 230 : base_init(NULL, &nk->base, next_oid(tr->store), true, name);
6833 230 : nk->type = kt;
6834 230 : nk->columns = list_create((fdestroy) &kc_destroy);
6835 230 : nk->t = t;
6836 230 : nk->idx = NULL;
6837 :
6838 230 : uk = (sql_ukey *) nk;
6839 :
6840 230 : if (nk->type == pkey)
6841 230 : t->pkey = uk;
6842 :
6843 230 : if ((res = ol_add(t->keys, &nk->base)))
6844 : return res;
6845 230 : if ((res = os_add(t->s->keys, tr, nk->base.name, dup_base(&nk->base))) ||
6846 230 : (isGlobal(t) && (res = os_add(tr->cat->objects, tr, nk->base.name, dup_base(&nk->base)))))
6847 0 : return res;
6848 :
6849 230 : const char *strnil = (const char*)ATOMnilptr(TYPE_str);
6850 460 : if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action, (check) ? &check : &strnil)))
6851 : return res;
6852 230 : *kres = nk;
6853 230 : return res;
6854 : }
6855 :
6856 : int
6857 0 : sql_trans_create_fkey(sql_fkey **kres, sql_trans *tr, sql_table *t, const char *name, key_type kt, sql_key *rkey, int on_delete, int on_update)
6858 : {
6859 : /* can only have keys between persistent tables */
6860 0 : sqlstore *store = tr->store;
6861 0 : int neg = -1, action = (on_update<<8) + on_delete, res = LOG_OK;
6862 0 : sql_key *nk;
6863 0 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
6864 0 : sql_table *syskey = find_sql_table(tr, syss, "keys");
6865 0 : sql_fkey *fk = NULL;
6866 0 : sql_table *dup = NULL;
6867 :
6868 0 : if (isTempTable(t))
6869 : return -1; /* TODO not sure here */
6870 :
6871 0 : if ((res = new_table(tr, t, &dup)))
6872 : return res;
6873 0 : t = dup;
6874 0 : nk = (kt != fkey) ? (sql_key *) ZNEW(sql_ukey)
6875 0 : : (sql_key *) ZNEW(sql_fkey);
6876 :
6877 0 : assert(name);
6878 0 : base_init(NULL, &nk->base, next_oid(tr->store), true, name);
6879 0 : nk->type = kt;
6880 0 : nk->columns = list_create((fdestroy) &kc_destroy);
6881 0 : nk->t = t;
6882 0 : if ((res = sql_trans_create_idx(&nk->idx, tr, t, name, (nk->type == fkey) ? join_idx : hash_idx)))
6883 : return res;
6884 0 : nk->idx->key = nk;
6885 :
6886 0 : fk = (sql_fkey *) nk;
6887 :
6888 0 : fk->on_delete = on_delete;
6889 0 : fk->on_update = on_update;
6890 :
6891 0 : fk->rkey = rkey->base.id;
6892 :
6893 0 : if ((res = ol_add(t->keys, &nk->base)))
6894 : return res;
6895 0 : if ((res = os_add(t->s->keys, tr, nk->base.name, dup_base(&nk->base))) ||
6896 0 : (isGlobal(t) && (res = os_add(tr->cat->objects, tr, nk->base.name, dup_base(&nk->base)))))
6897 0 : return res;
6898 :
6899 0 : if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action)))
6900 : return res;
6901 :
6902 0 : if ((res = sql_trans_create_dependency(tr, ((sql_fkey *) nk)->rkey, nk->base.id, FKEY_DEPENDENCY)))
6903 : return res;
6904 0 : *kres = (sql_fkey*) nk;
6905 0 : return res;
6906 : }
6907 :
6908 : int
6909 230 : sql_trans_create_kc(sql_trans *tr, sql_key *k, sql_column *c)
6910 : {
6911 230 : sqlstore *store = tr->store;
6912 230 : sql_kc *kc = ZNEW(sql_kc);
6913 230 : int nr = list_length(k->columns);
6914 230 : sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
6915 230 : sql_table *syskc = find_sql_table(tr, syss, "objects");
6916 230 : int res = LOG_OK;
6917 :
6918 230 : assert(c);
6919 230 : kc->c = c;
6920 230 : list_append(k->columns, kc);
6921 230 : if (k->idx && (res = sql_trans_create_ic(tr, k->idx, c)))
6922 : return res;
6923 :
6924 230 : if (k->type == pkey) {
6925 230 : if ((res = sql_trans_create_dependency(tr, c->base.id, k->base.id, KEY_DEPENDENCY)))
6926 : return res;
6927 230 : if ((res = sql_trans_alter_null(tr, c, 0))) /* should never trigger error */
6928 : return res;
6929 : }
6930 :
6931 230 : if ((res = store->table_api.table_insert(tr, syskc, &k->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))))
6932 : return res;
6933 : return res;
6934 : }
6935 :
6936 : int
6937 0 : sql_trans_create_fkc(sql_trans *tr, sql_fkey *fk, sql_column *c)
6938 : {
6939 0 : sqlstore *store = tr->store;
6940 0 : sql_key *k = (sql_key *) fk;
6941 0 : sql_kc *kc = ZNEW(sql_kc);
6942 0 : int nr = list_length(k->columns);
6943 0 : sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp");
6944 0 : sql_table *syskc = find_sql_table(tr, syss, "objects");
6945 0 : int res = LOG_OK;
6946 :
6947 0 : assert(c);
6948 0 : kc->c = c;
6949 0 : list_append(k->columns, kc);
6950 0 : if (k->idx && (res = sql_trans_create_ic(tr, k->idx, c)))
6951 : return res;
6952 :
6953 0 : if ((res = sql_trans_create_dependency(tr, c->base.id, k->base.id, FKEY_DEPENDENCY)))
6954 : return res;
6955 :
6956 0 : if ((res = store->table_api.table_insert(tr, syskc, &k->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))))
6957 : return res;
6958 : return res;
6959 : }
6960 :
6961 : static sql_idx *
6962 6262 : table_has_idx( sql_table *t, list *keycols)
6963 : {
6964 6262 : node *n, *m, *o;
6965 6262 : char *found = NULL;
6966 6262 : int len = list_length(keycols);
6967 6262 : found = NEW_ARRAY(char, len);
6968 6262 : if (!found)
6969 : return NULL;
6970 8182 : if (t->idxs) for ( n = ol_first_node(t->idxs); n; n = n->next ) {
6971 2014 : sql_idx *i = n->data;
6972 2014 : int nr;
6973 :
6974 2014 : memset(found, 0, len);
6975 4173 : for (m = keycols->h, nr = 0; m; m = m->next, nr++ ) {
6976 2159 : sql_kc *kc = m->data;
6977 :
6978 4238 : for (o = i->columns->h; o; o = o->next) {
6979 2254 : sql_kc *ikc = o->data;
6980 :
6981 2254 : if (kc->c == ikc->c) {
6982 175 : found[nr] = 1;
6983 175 : break;
6984 : }
6985 : }
6986 : }
6987 2146 : for (nr = 0; nr<len; nr++)
6988 2052 : if (!found[nr])
6989 : break;
6990 2014 : if (nr == len) {
6991 94 : _DELETE(found);
6992 94 : return i;
6993 : }
6994 : }
6995 6168 : if (found)
6996 6168 : _DELETE(found);
6997 6168 : return NULL;
6998 : }
6999 :
7000 : sql_key *
7001 6992 : key_create_done(sql_trans *tr, allocator *sa, sql_key *k)
7002 : {
7003 6992 : sql_idx *i;
7004 6992 : sqlstore *store = tr->store;
7005 :
7006 6992 : if (k->type != fkey && k->type != ckey) {
7007 6032 : if ((i = table_has_idx(k->t, k->columns)) != NULL) {
7008 : /* use available hash, or use the order */
7009 94 : if (hash_index(i->type)) {
7010 93 : k->idx = i;
7011 93 : if (!k->idx->key)
7012 0 : k->idx->key = k;
7013 : }
7014 : }
7015 :
7016 : /* we need to create an index */
7017 6032 : k->idx = create_sql_idx(store, sa, k->t, k->base.name, hash_idx);
7018 6032 : k->idx->key = k;
7019 :
7020 12677 : for (node *n=k->columns->h; n; n = n->next) {
7021 6645 : sql_kc *kc = n->data;
7022 :
7023 6645 : create_sql_ic(store, sa, k->idx, kc->c);
7024 : }
7025 : }
7026 6992 : k->idx = create_sql_idx_done(tr, k->idx);
7027 6992 : return k;
7028 : }
7029 :
7030 : int
7031 230 : sql_trans_key_done(sql_trans *tr, sql_key *k)
7032 : {
7033 230 : sql_idx *i;
7034 230 : int res = LOG_OK;
7035 :
7036 230 : if (k->type != fkey) {
7037 230 : if ((i = table_has_idx(k->t, k->columns)) != NULL) {
7038 : /* use available hash, or use the order */
7039 0 : if (hash_index(i->type)) {
7040 0 : k->idx = i;
7041 0 : if (!k->idx->key)
7042 0 : k->idx->key = k;
7043 : }
7044 0 : return res;
7045 : }
7046 :
7047 : /* we need to create an index */
7048 230 : if ((res = sql_trans_create_idx(&k->idx, tr, k->t, k->base.name, hash_idx)))
7049 : return res;
7050 230 : k->idx->key = k;
7051 :
7052 460 : for (node *n=k->columns->h; n; n = n->next) {
7053 230 : sql_kc *kc = n->data;
7054 :
7055 230 : if ((res = sql_trans_create_ic(tr, k->idx, kc->c)))
7056 0 : return res;
7057 : }
7058 : }
7059 230 : k->idx = create_sql_idx_done(tr, k->idx);
7060 230 : return res;
7061 : }
7062 :
7063 : int
7064 423 : sql_trans_drop_key(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
7065 : {
7066 423 : sqlstore *store = tr->store;
7067 423 : sql_base *b = os_find_id(s->keys, tr, id);
7068 423 : sql_key *k = (sql_key*)b;
7069 423 : sql_table *t = k->t;
7070 423 : int res = LOG_OK;
7071 423 : sql_table *dup = NULL;
7072 :
7073 423 : if ((res = new_table(tr, t, &dup)))
7074 : return res;
7075 423 : t = dup;
7076 423 : k = (sql_key*)os_find_id(s->keys, tr, id); /* fetch updated key */
7077 :
7078 423 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
7079 278 : sqlid *local_id = MNEW(sqlid);
7080 278 : if (!local_id)
7081 : return -1;
7082 :
7083 278 : if (!tr->dropped) {
7084 2 : tr->dropped = list_create((fdestroy) &id_destroy);
7085 2 : if (!tr->dropped) {
7086 0 : _DELETE(local_id);
7087 0 : return -1;
7088 : }
7089 : }
7090 278 : *local_id = k->base.id;
7091 278 : list_append(tr->dropped, local_id);
7092 : }
7093 :
7094 423 : if (k->idx && (res = sql_trans_drop_idx(tr, s, k->idx->base.id, drop_action)))
7095 : return res;
7096 423 : if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */
7097 : return res;
7098 :
7099 423 : if ((res = sys_drop_key(tr, k, drop_action)))
7100 : return res;
7101 :
7102 : /*Clean the key from the keys*/
7103 423 : node *n = ol_find_name(k->t->keys, k->base.name);
7104 423 : if (n)
7105 423 : ol_del(k->t->keys, store, n);
7106 :
7107 423 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
7108 1 : list_destroy(tr->dropped);
7109 1 : tr->dropped = NULL;
7110 : }
7111 : return res;
7112 : }
7113 :
7114 : int
7115 230 : sql_trans_create_idx(sql_idx **i, sql_trans *tr, sql_table *t, const char *name, idx_type it)
7116 : {
7117 : /* can only have idxs between persistent tables */
7118 230 : sqlstore *store = tr->store;
7119 230 : sql_idx *ni = ZNEW(sql_idx);
7120 230 : sql_schema *syss = find_sql_schema(tr, isGlobal(t)?"sys":"tmp");
7121 230 : sql_table *sysidx = find_sql_table(tr, syss, "idxs");
7122 230 : int res = LOG_OK;
7123 :
7124 230 : assert(it != oph_idx && it != no_idx && it != new_idx_types);
7125 230 : assert(name);
7126 230 : base_init(NULL, &ni->base, next_oid(tr->store), true, name);
7127 230 : ni->type = it;
7128 230 : ni->columns = list_create((fdestroy) &kc_destroy);
7129 230 : ni->t = t;
7130 230 : ni->key = NULL;
7131 :
7132 230 : if ((res = ol_add(t->idxs, &ni->base)))
7133 : return res;
7134 230 : if (isGlobal(t) && (res = os_add(t->s->idxs, tr, ni->base.name, dup_base(&ni->base))))
7135 : return res;
7136 :
7137 230 : ATOMIC_PTR_INIT(&ni->data, NULL);
7138 230 : if (!isDeclaredTable(t) && isTable(ni->t) && idx_has_column(ni->type))
7139 230 : if ((res = store->storage_api.create_idx(tr, ni))) {
7140 : return res;
7141 : }
7142 230 : if (!isDeclaredTable(t))
7143 230 : if ((res = store->table_api.table_insert(tr, sysidx, &ni->base.id, &t->base.id, &ni->type, &ni->base.name))) {
7144 : return res;
7145 : }
7146 230 : *i = ni;
7147 230 : return res;
7148 : }
7149 :
7150 : int
7151 230 : sql_trans_create_ic(sql_trans *tr, sql_idx *i, sql_column *c)
7152 : {
7153 230 : sqlstore *store = tr->store;
7154 230 : sql_kc *ic = ZNEW(sql_kc);
7155 230 : int nr = list_length(i->columns);
7156 230 : sql_schema *syss = find_sql_schema(tr, isGlobal(i->t)?"sys":"tmp");
7157 230 : sql_table *sysic = find_sql_table(tr, syss, "objects");
7158 230 : int res = LOG_OK;
7159 :
7160 230 : assert(c);
7161 230 : ic->c = c;
7162 230 : list_append(i->columns, ic);
7163 :
7164 230 : if ((res = store->table_api.table_insert(tr, sysic, &i->base.id, &ic->c->base.name, &nr, ATOMnilptr(TYPE_int))))
7165 : return res;
7166 : return res;
7167 : }
7168 :
7169 : int
7170 586 : sql_trans_drop_idx(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
7171 : {
7172 586 : sqlstore *store = tr->store;
7173 586 : sql_idx *i = schema_find_idx_id(tr, s, id);
7174 586 : int res = LOG_OK;
7175 :
7176 586 : if (!i) /* already dropped */
7177 : return res;
7178 :
7179 582 : sql_table *t = NULL;
7180 582 : if ((res = new_table(tr, i->t, &t)))
7181 : return res;
7182 582 : i = schema_find_idx_id(tr, s, id); /* fetch updated idx */
7183 :
7184 582 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
7185 282 : sqlid *local_id = MNEW(sqlid);
7186 282 : if (!local_id)
7187 : return -1;
7188 :
7189 282 : if (!tr->dropped) {
7190 0 : tr->dropped = list_create((fdestroy) &id_destroy);
7191 0 : if (!tr->dropped) {
7192 0 : _DELETE(local_id);
7193 0 : return -1;
7194 : }
7195 : }
7196 282 : *local_id = i->base.id;
7197 282 : list_append(tr->dropped, local_id);
7198 : }
7199 :
7200 582 : if (!isNew(i) && (res = sql_trans_add_dependency_change(tr, i->t->base.id, ddl)))
7201 : return res;
7202 582 : if (!isNew(i) && isGlobal(i->t) && !isGlobalTemp(i->t) && (res = sql_trans_add_dependency(tr, i->t->base.id, dml)))
7203 : return res;
7204 582 : if ((res = sys_drop_idx(tr, i, drop_action)))
7205 : return res;
7206 582 : if ((res = store_reset_sql_functions(tr, i->t->base.id))) /* reset sql functions depending on the table */
7207 : return res;
7208 :
7209 582 : node *n = ol_find_name(i->t->idxs, i->base.name);
7210 582 : if (n)
7211 582 : ol_del(i->t->idxs, store, n);
7212 :
7213 582 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
7214 1 : list_destroy(tr->dropped);
7215 1 : tr->dropped = NULL;
7216 : }
7217 : return res;
7218 : }
7219 :
7220 :
7221 : static int
7222 344 : sql_trans_create_table_trigger(sql_trigger **tres, sql_trans *tr, sql_table *t, const char *name,
7223 : sht time, sht orientation, sht event, const char *old_name, const char *new_name,
7224 : const char *condition, const char *statement )
7225 : {
7226 344 : sqlstore *store = tr->store;
7227 344 : sql_schema *syss = (t != NULL) ? find_sql_schema(tr, isGlobal(t) ? "sys":"tmp") : find_sql_schema(tr, "sys");
7228 344 : sql_table *systrigger = find_sql_table(tr, syss, "triggers");
7229 344 : char *strnil = (char*)ATOMnilptr(TYPE_str);
7230 344 : sql_table *dup = NULL;
7231 344 : int res = LOG_OK;
7232 :
7233 344 : assert(name);
7234 :
7235 344 : if ( t && (res = new_table(tr, t, &dup)))
7236 : return res;
7237 344 : t = dup;
7238 344 : sql_trigger *nt = ZNEW(sql_trigger);
7239 344 : base_init(NULL, &nt->base, next_oid(tr->store), true, name);
7240 344 : nt->columns = list_create((fdestroy) &kc_destroy);
7241 344 : nt->t = t;
7242 344 : nt->time = time;
7243 344 : nt->orientation = orientation;
7244 344 : nt->event = event;
7245 344 : nt->old_name = nt->new_name = nt->condition = NULL;
7246 344 : if (old_name)
7247 27 : nt->old_name =_STRDUP(old_name);
7248 344 : if (new_name)
7249 40 : nt->new_name =_STRDUP(new_name);
7250 344 : if (condition)
7251 0 : nt->condition =_STRDUP(condition);
7252 344 : nt->statement =_STRDUP(statement);
7253 344 : if(t) {
7254 344 : assert(isGlobal(t));
7255 344 : if ((res = ol_add(t->triggers, &nt->base)) ||
7256 344 : (res = os_add(t->s->triggers, tr, nt->base.name, dup_base(&nt->base)))) {
7257 0 : return res;
7258 : }
7259 : }
7260 344 : sqlid tid = t? t->base.id : int_nil;
7261 :
7262 384 : if ((res = store->table_api.table_insert(tr, systrigger, &nt->base.id, &nt->base.name, &tid, &nt->time, &nt->orientation,
7263 384 : &nt->event, (nt->old_name)?&nt->old_name:&strnil, (nt->new_name)?&nt->new_name:&strnil,
7264 344 : (nt->condition)?&nt->condition:&strnil, &nt->statement))) {
7265 : return res;
7266 : }
7267 344 : *tres = nt;
7268 344 : return res;
7269 : }
7270 :
7271 : int
7272 348 : sql_trans_create_trigger(sql_trigger **tres, sql_trans *tr, sql_table *t, const char *name,
7273 : sht time, sht orientation, sht event, const char *old_name, const char *new_name,
7274 : const char *condition, const char *statement )
7275 : {
7276 348 : if (t)
7277 344 : return sql_trans_create_table_trigger(
7278 : tres, tr, t, name, time,
7279 : orientation, event, old_name,
7280 : new_name, condition, statement);
7281 :
7282 : // triggers not bound to objects (e.g. table)
7283 : // are added to sys->triggers
7284 :
7285 4 : sqlstore *store = tr->store;
7286 4 : sql_schema *syss = find_sql_schema(tr, "sys");
7287 4 : sql_table *systrigger = find_sql_table(tr, syss, "triggers");
7288 4 : char *strnil = (char*)ATOMnilptr(TYPE_str);
7289 4 : int res = LOG_OK;
7290 :
7291 4 : assert(name);
7292 :
7293 4 : sql_trigger *nt = ZNEW(sql_trigger);
7294 4 : base_init(NULL, &nt->base, next_oid(tr->store), true, name);
7295 4 : nt->time = time;
7296 4 : nt->orientation = orientation;
7297 4 : nt->event = event;
7298 4 : nt->old_name = nt->new_name = nt->condition = NULL;
7299 4 : if (old_name)
7300 0 : nt->old_name =_STRDUP(old_name);
7301 4 : if (new_name)
7302 0 : nt->new_name =_STRDUP(new_name);
7303 4 : if (condition)
7304 0 : nt->condition =_STRDUP(condition);
7305 4 : nt->statement =_STRDUP(statement);
7306 4 : if ((res = os_add(syss->triggers, tr, nt->base.name, &nt->base))) {
7307 0 : trigger_destroy(store, nt);
7308 0 : return res;
7309 : }
7310 4 : sqlid tid = int_nil;
7311 :
7312 4 : if ((res = store->table_api.table_insert(tr, systrigger, &nt->base.id, &nt->base.name, &tid, &nt->time, &nt->orientation,
7313 4 : &nt->event, (nt->old_name)?&nt->old_name:&strnil, (nt->new_name)?&nt->new_name:&strnil,
7314 4 : (nt->condition)?&nt->condition:&strnil, &nt->statement))) {
7315 0 : trigger_destroy(store, nt);
7316 0 : return res;
7317 : }
7318 :
7319 4 : *tres = nt;
7320 4 : return res;
7321 : }
7322 :
7323 : int
7324 91 : sql_trans_drop_trigger(sql_trans *tr, sql_schema *s, sqlid id, int drop_action)
7325 : {
7326 91 : sqlstore *store = tr->store;
7327 91 : sql_base *b = os_find_id(s->triggers, tr, id);
7328 91 : int res = LOG_OK;
7329 :
7330 91 : if (!b) /* already dropped */
7331 : return res;
7332 :
7333 91 : sql_trigger *i = (sql_trigger*)b;
7334 91 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
7335 2 : sqlid *local_id = MNEW(sqlid);
7336 2 : if (!local_id)
7337 : return -1;
7338 :
7339 2 : if (! tr->dropped) {
7340 0 : tr->dropped = list_create((fdestroy) &id_destroy);
7341 0 : if (!tr->dropped) {
7342 0 : _DELETE(local_id);
7343 0 : return -1;
7344 : }
7345 : }
7346 2 : *local_id = i->base.id;
7347 2 : list_append(tr->dropped, local_id);
7348 : }
7349 :
7350 91 : if (i->t) {
7351 88 : if ((res = store_reset_sql_functions(tr, i->t->base.id))) /* reset sql functions depending on the table */
7352 : return res;
7353 88 : node *n = ol_find_name(i->t->triggers, i->base.name);
7354 88 : if (n)
7355 85 : ol_del(i->t->triggers, store, n);
7356 : }
7357 91 : if ((res = sys_drop_trigger(tr, i)))
7358 : return res;
7359 :
7360 88 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
7361 0 : list_destroy(tr->dropped);
7362 0 : tr->dropped = NULL;
7363 : }
7364 : return res;
7365 : }
7366 :
7367 : static sql_sequence *
7368 712 : create_sql_sequence_with_id(allocator *sa, sqlid id, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc,
7369 : lng cacheinc, bit cycle)
7370 : {
7371 712 : sql_sequence *seq = SA_ZNEW(sa, sql_sequence);
7372 :
7373 712 : assert(name);
7374 712 : base_init(sa, &seq->base, id, true, name);
7375 712 : seq->start = start;
7376 712 : seq->minvalue = min;
7377 712 : seq->maxvalue = max;
7378 712 : seq->increment = inc;
7379 712 : seq->cacheinc = cacheinc;
7380 712 : seq->cycle = cycle;
7381 712 : seq->s = s;
7382 712 : return seq;
7383 : }
7384 :
7385 : sql_sequence *
7386 365 : create_sql_sequence(sqlstore *store, allocator *sa, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc,
7387 : lng cacheinc, bit cycle)
7388 : {
7389 365 : return create_sql_sequence_with_id(sa, next_oid(store), s, name, start, min, max, inc, cacheinc, cycle);
7390 : }
7391 :
7392 : int
7393 347 : sql_trans_create_sequence(sql_trans *tr, sql_schema *s, const char *name, lng start, lng min, lng max, lng inc,
7394 : lng cacheinc, bit cycle, bit bedropped)
7395 : {
7396 347 : sqlstore *store = tr->store;
7397 347 : sql_schema *syss = find_sql_schema(tr, "sys");
7398 347 : sql_table *sysseqs = find_sql_table(tr, syss, "sequences");
7399 347 : sql_sequence *seq = create_sql_sequence_with_id(NULL, next_oid(tr->store), s, name, start, min, max, inc, cacheinc, cycle);
7400 347 : int res = LOG_OK;
7401 :
7402 347 : if ((res = os_add(s->seqs, tr, seq->base.name, &seq->base)))
7403 : return res;
7404 347 : if ((res = store->table_api.table_insert(tr, sysseqs, &seq->base.id, &s->base.id, &seq->base.name, &seq->start, &seq->minvalue,
7405 : &seq->maxvalue, &seq->increment, &seq->cacheinc, &seq->cycle)))
7406 : return res;
7407 :
7408 : /*Create a BEDROPPED dependency for a SERIAL COLUMN*/
7409 347 : if (bedropped) {
7410 228 : if ((res = sql_trans_create_dependency(tr, seq->base.id, seq->base.id, BEDROPPED_DEPENDENCY)))
7411 : return res;
7412 228 : if (!isNew(seq) && (res = sql_trans_add_dependency(tr, seq->base.id, ddl)))
7413 : return res;
7414 : }
7415 : return res;
7416 : }
7417 :
7418 : int
7419 61 : sql_trans_drop_sequence(sql_trans *tr, sql_schema *s, sql_sequence *seq, int drop_action)
7420 : {
7421 61 : int res = LOG_OK;
7422 :
7423 61 : if (drop_action == DROP_CASCADE_START || drop_action == DROP_CASCADE) {
7424 22 : sqlid* local_id = MNEW(sqlid);
7425 22 : if (!local_id)
7426 : return -1;
7427 :
7428 22 : if (!tr->dropped) {
7429 22 : tr->dropped = list_create((fdestroy) &id_destroy);
7430 22 : if (!tr->dropped) {
7431 0 : _DELETE(local_id);
7432 0 : return -1;
7433 : }
7434 : }
7435 22 : *local_id = seq->base.id;
7436 22 : list_append(tr->dropped, local_id);
7437 : }
7438 :
7439 61 : if ((res = sys_drop_sequence(tr, seq, drop_action)))
7440 : return res;
7441 61 : if ((res = os_del(s->seqs, tr, seq->base.name, dup_base(&seq->base))))
7442 : return res;
7443 :
7444 61 : if (drop_action == DROP_CASCADE_START && tr->dropped) {
7445 22 : list_destroy(tr->dropped);
7446 22 : tr->dropped = NULL;
7447 : }
7448 : return res;
7449 : }
7450 :
7451 : int
7452 45 : sql_trans_alter_sequence(sql_trans *tr, sql_sequence *seq, lng min, lng max, lng inc, lng cache, bit cycle)
7453 : {
7454 45 : sqlstore *store = tr->store;
7455 45 : sql_schema *syss = find_sql_schema(tr, "sys");
7456 45 : sql_table *seqs = find_sql_table(tr, syss, "sequences");
7457 45 : oid rid = store->table_api.column_find_row(tr, find_sql_column(seqs, "id"), &seq->base.id, NULL);
7458 45 : sql_column *c;
7459 45 : int res = LOG_OK;
7460 :
7461 45 : if (is_oid_nil(rid))
7462 : return -1;
7463 45 : if (!is_lng_nil(min) && seq->minvalue != min) {
7464 33 : seq->minvalue = min;
7465 33 : c = find_sql_column(seqs, "minvalue");
7466 33 : if ((res = store->table_api.column_update_value(tr, c, rid, &seq->minvalue)))
7467 : return res;
7468 : }
7469 45 : if (!is_lng_nil(max) && seq->maxvalue != max) {
7470 7 : seq->maxvalue = max;
7471 7 : c = find_sql_column(seqs, "maxvalue");
7472 7 : if ((res = store->table_api.column_update_value(tr, c, rid, &seq->maxvalue)))
7473 : return res;
7474 : }
7475 45 : if (!is_lng_nil(inc) && seq->increment != inc) {
7476 7 : seq->increment = inc;
7477 7 : c = find_sql_column(seqs, "increment");
7478 7 : if ((res = store->table_api.column_update_value(tr, c, rid, &seq->increment)))
7479 : return res;
7480 : }
7481 45 : if (!is_lng_nil(cache) && seq->cacheinc != cache) {
7482 0 : seq->cacheinc = cache;
7483 0 : c = find_sql_column(seqs, "cacheinc");
7484 0 : if ((res = store->table_api.column_update_value(tr, c, rid, &seq->cacheinc)))
7485 : return res;
7486 : }
7487 45 : if (!is_bit_nil(cycle) && seq->cycle != cycle) {
7488 7 : seq->cycle = cycle != 0;
7489 7 : c = find_sql_column(seqs, "cycle");
7490 7 : if ((res = store->table_api.column_update_value(tr, c, rid, &seq->cycle)))
7491 : return res;
7492 : }
7493 : return res;
7494 : }
7495 :
7496 : int
7497 47 : sql_trans_sequence_restart(sql_trans *tr, sql_sequence *seq, lng start)
7498 : {
7499 47 : int res = LOG_OK;
7500 47 : sqlstore *store = tr->store;
7501 :
7502 47 : if (!is_lng_nil(start) && seq->start != start) { /* new valid value, change */
7503 16 : sql_schema *syss = find_sql_schema(tr, "sys");
7504 16 : sql_table *seqs = find_sql_table(tr, syss, "sequences");
7505 16 : oid rid = store->table_api.column_find_row(tr, find_sql_column(seqs, "id"), &seq->base.id, NULL);
7506 16 : sql_column *c = find_sql_column(seqs, "start");
7507 :
7508 16 : assert(!is_oid_nil(rid));
7509 16 : seq->start = start;
7510 16 : if ((res = store->table_api.column_update_value(tr, c, rid, &start)))
7511 : return res;
7512 : }
7513 47 : return seq_restart(tr->store, seq, start) ? 0 : -4;
7514 : }
7515 :
7516 : sql_session *
7517 37993 : sql_session_create(sqlstore *store, allocator *sa, int ac)
7518 : {
7519 37993 : sql_session *s;
7520 :
7521 37993 : if (store->singleuser > 1) {
7522 0 : TRC_ERROR(SQL_STORE, "No second connection allowed in singleuser mode\n");
7523 0 : return NULL;
7524 : }
7525 :
7526 37993 : s = ZNEW(sql_session);
7527 37993 : if (!s)
7528 : return NULL;
7529 37993 : s->sa = sa;
7530 37993 : assert(sa);
7531 37993 : s->tr = sql_trans_create_(store, NULL, NULL);
7532 37993 : if (!s->tr) {
7533 0 : _DELETE(s);
7534 0 : return NULL;
7535 : }
7536 37993 : s->tr->active = 0;
7537 37993 : if (!sql_session_reset(s, ac)) {
7538 0 : sql_trans_destroy(s->tr);
7539 0 : _DELETE(s);
7540 0 : return NULL;
7541 : }
7542 37993 : if (store->singleuser)
7543 0 : store->singleuser = 2;
7544 : return s;
7545 : }
7546 :
7547 : void
7548 37993 : sql_session_destroy(sql_session *s)
7549 : {
7550 37993 : if (s->tr) {
7551 37993 : sqlstore *store = s->tr->store;
7552 37993 : if (store->singleuser)
7553 0 : store->singleuser = 1;
7554 : }
7555 : // TODO check if s->tr is not always there
7556 37993 : assert(!s->tr || s->tr->active == 0);
7557 37993 : if (s->tr)
7558 37993 : sql_trans_destroy(s->tr);
7559 37993 : _DELETE(s);
7560 37993 : }
7561 :
7562 : int
7563 37993 : sql_session_reset(sql_session *s, int ac)
7564 : {
7565 37993 : if (!s->tr)
7566 : return 0;
7567 :
7568 37993 : assert(s->tr && s->tr->active == 0);
7569 37993 : s->schema_name = s->def_schema_name;
7570 37993 : s->schema = NULL;
7571 37993 : s->auto_commit = s->ac_on_commit = ac;
7572 37993 : s->level = tr_serializable;
7573 37993 : return 1;
7574 : }
7575 :
7576 : int
7577 256202 : sql_trans_begin(sql_session *s)
7578 : {
7579 256202 : sql_trans *tr = s->tr;
7580 256202 : sqlstore *store = tr->store;
7581 :
7582 256202 : store_lock(store);
7583 256345 : TRC_DEBUG(SQL_STORE, "Enter sql_trans_begin for transaction: " ULLFMT "\n", tr->tid);
7584 256345 : tr->ts = store_timestamp(store);
7585 256345 : if (s->schema_name && !(s->schema = find_sql_schema(tr, s->schema_name)))
7586 3 : s->schema_name = s->def_schema_name;
7587 256345 : if (!s->schema_name)
7588 37992 : s->schema_name = "sys";
7589 256345 : if (s->schema_name && !(s->schema = find_sql_schema(tr, s->schema_name))) {
7590 2 : TRC_DEBUG(SQL_STORE, "Exit sql_trans_begin for transaction: " ULLFMT " with error, the schema %s was not found\n", tr->tid, s->schema_name);
7591 2 : store_unlock(store);
7592 2 : return -3;
7593 : }
7594 256343 : tr->active = 1;
7595 :
7596 512686 : int res = ATOMIC_GET(&s->schema_version) ?
7597 256343 : ATOMIC_GET(&s->schema_version) != ATOMIC_GET(&tr->cat->schema_version) : 0;
7598 256343 : ATOMIC_SET(&s->schema_version, tr->cat->schema_version);
7599 :
7600 256343 : ATOMIC_INC(&store->nr_active);
7601 256343 : list_append(store->active, tr);
7602 :
7603 256343 : TRC_DEBUG(SQL_STORE, "Exit sql_trans_begin for transaction: " ULLFMT "\n", tr->tid);
7604 256343 : store_unlock(store);
7605 256342 : s->status = tr->status = 0;
7606 256342 : return res;
7607 : }
7608 :
7609 : int
7610 256318 : sql_trans_end(sql_session *s, int ok)
7611 : {
7612 256318 : int res = SQL_OK;
7613 256318 : TRC_DEBUG(SQL_STORE, "End of transaction: " ULLFMT "\n", s->tr->tid);
7614 256318 : if (ok == SQL_OK) {
7615 194892 : assert(!s->status && !s->tr->status);
7616 194892 : res = sql_trans_commit(s->tr);
7617 : }
7618 256299 : if (ok == SQL_ERR || res != SQL_OK) /* if a conflict happened, it was already rollbacked */
7619 62469 : sql_trans_rollback(s->tr, false);
7620 256298 : assert(s->tr->active);
7621 256298 : sqlstore *store = s->tr->store;
7622 256298 : store_lock(store);
7623 256343 : s->tr->active = 0;
7624 256343 : s->tr->status = 0;
7625 256343 : s->auto_commit = s->ac_on_commit;
7626 256343 : s->schema = NULL;
7627 256343 : list_remove_data(store->active, NULL, s->tr);
7628 256343 : ATOMIC_SET(&store->lastactive, GDKusec());
7629 256343 : ATOMIC_DEC(&store->nr_active);
7630 256343 : ulng oldest = store_get_timestamp(store);
7631 256343 : if (store->active && store->active->h) {
7632 1814932 : for(node *n = store->active->h; n; n = n->next) {
7633 1643667 : sql_trans *tr = n->data;
7634 1643667 : if (tr->ts < oldest)
7635 : oldest = tr->ts;
7636 : }
7637 : }
7638 256343 : ATOMIC_SET(&store->oldest, oldest);
7639 256343 : assert(list_length(store->active) == (int) ATOMIC_GET(&store->nr_active));
7640 256343 : store_unlock(store);
7641 256343 : return res;
7642 : }
7643 :
7644 : void
7645 1065 : find_partition_type(sql_subtype *tpe, sql_table *mt)
7646 : {
7647 1065 : if (isPartitionedByColumnTable(mt)) {
7648 913 : *tpe = mt->part.pcol->type;
7649 152 : } else if (isPartitionedByExpressionTable(mt)) {
7650 152 : *tpe = mt->part.pexp->type;
7651 : } else {
7652 0 : assert(0);
7653 : }
7654 1065 : }
7655 :
7656 : static int
7657 51 : convert_part_values(sql_trans *tr, sql_table *mt )
7658 : {
7659 51 : sql_subtype found = { 0 };
7660 51 : int localtype;
7661 51 : find_partition_type(&found, mt);
7662 51 : localtype = found.type->localtype;
7663 :
7664 51 : if (localtype != TYPE_str && mt->members && list_length(mt->members)) {
7665 144 : for (node *n = mt->members->h; n; n = n->next) {
7666 99 : sql_part *p = n->data;
7667 :
7668 99 : if (isListPartitionTable(mt)) {
7669 129 : for (node *m = p->part.values->h; m; m = m->next) {
7670 96 : sql_part_value *v = (sql_part_value*) m->data, ov = *v;
7671 96 : ValRecord vvalue;
7672 96 : ptr ok;
7673 :
7674 96 : vvalue = (ValRecord) {.vtype = TYPE_void,};
7675 96 : ok = VALinit(&vvalue, TYPE_str, v->value);
7676 96 : if (ok)
7677 96 : ok = VALconvert(localtype, &vvalue);
7678 96 : if (ok) {
7679 96 : ok = v->value = NEW_ARRAY(char, vvalue.len);
7680 96 : if (ok) {
7681 96 : memcpy(v->value, VALget(&vvalue), vvalue.len);
7682 96 : v->length = vvalue.len;
7683 : }
7684 : }
7685 96 : VALclear(&vvalue);
7686 96 : if (!ok)
7687 0 : return -1;
7688 96 : _DELETE(ov.value);
7689 : }
7690 66 : } else if (isRangePartitionTable(mt)) {
7691 66 : ValRecord vmin, vmax;
7692 66 : ptr ok;
7693 :
7694 66 : vmin = vmax = (ValRecord) {.vtype = TYPE_void,};
7695 66 : ok = VALinit(&vmin, TYPE_str, p->part.range.minvalue);
7696 66 : if (ok)
7697 66 : ok = VALinit(&vmax, TYPE_str, p->part.range.maxvalue);
7698 66 : _DELETE(p->part.range.minvalue);
7699 66 : _DELETE(p->part.range.maxvalue);
7700 66 : if (ok) {
7701 66 : if (strNil((const char *)VALget(&vmin)) &&
7702 42 : strNil((const char *)VALget(&vmax))) {
7703 32 : const void *nil_ptr = ATOMnilptr(localtype);
7704 32 : size_t nil_len = ATOMlen(localtype, nil_ptr);
7705 :
7706 32 : p->part.range.minvalue = NEW_ARRAY(char, nil_len);
7707 32 : p->part.range.maxvalue = NEW_ARRAY(char, nil_len);
7708 32 : if (p->part.range.minvalue == NULL ||
7709 : p->part.range.maxvalue == NULL) {
7710 0 : ok = NULL;
7711 0 : _DELETE(p->part.range.minvalue);
7712 0 : _DELETE(p->part.range.maxvalue);
7713 : } else {
7714 32 : memcpy(p->part.range.minvalue, nil_ptr, nil_len);
7715 32 : memcpy(p->part.range.maxvalue, nil_ptr, nil_len);
7716 32 : p->part.range.minlength = nil_len;
7717 32 : p->part.range.maxlength = nil_len;
7718 : }
7719 : } else {
7720 34 : ok = VALconvert(localtype, &vmin);
7721 34 : if (ok)
7722 34 : ok = VALconvert(localtype, &vmax);
7723 34 : if (ok) {
7724 34 : p->part.range.minvalue = NEW_ARRAY(char, vmin.len);
7725 34 : p->part.range.maxvalue = NEW_ARRAY(char, vmax.len);
7726 34 : if (p->part.range.minvalue == NULL ||
7727 : p->part.range.maxvalue == NULL) {
7728 0 : ok = NULL;
7729 0 : _DELETE(p->part.range.minvalue);
7730 0 : _DELETE(p->part.range.maxvalue);
7731 : } else {
7732 34 : memcpy(p->part.range.minvalue, VALget(&vmin), vmin.len);
7733 34 : memcpy(p->part.range.maxvalue, VALget(&vmax), vmax.len);
7734 34 : p->part.range.minlength = vmin.len;
7735 34 : p->part.range.maxlength = vmax.len;
7736 : }
7737 : }
7738 : }
7739 66 : if (ok && isPartitionedByColumnTable(p->t))
7740 64 : col_set_range(tr, p, true);
7741 : }
7742 66 : VALclear(&vmin);
7743 66 : VALclear(&vmax);
7744 66 : if (!ok)
7745 0 : return -1;
7746 : }
7747 : }
7748 : }
7749 : return 0;
7750 : }
7751 :
7752 : int
7753 357 : sql_trans_convert_partitions(sql_trans *tr)
7754 : {
7755 357 : struct os_iter si;
7756 357 : os_iterator(&si, tr->cat->schemas, tr, NULL);
7757 1969 : for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
7758 1612 : sql_schema *ss = (sql_schema*)b;
7759 1612 : struct os_iter oi;
7760 1612 : os_iterator(&oi, ss->tables, tr, NULL);
7761 26934 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
7762 25322 : sql_table *tt = (sql_table*)b;
7763 25322 : if (isPartitionedByColumnTable(tt) || isPartitionedByExpressionTable(tt)) {
7764 51 : if (convert_part_values(tr, tt) < 0)
7765 0 : return -1;
7766 : }
7767 : }
7768 : }
7769 : return 0;
7770 : }
7771 :
7772 : void
7773 119 : store_printinfo(sqlstore *store)
7774 : {
7775 119 : if (!MT_lock_trytime(&store->commit, 1000)) {
7776 0 : printf("WAL is currently locked, so no WAL information\n");
7777 0 : return;
7778 : }
7779 119 : printf("WAL:\n");
7780 119 : printf("SQL store oldest pending "ULLFMT"\n", store->oldest_pending);
7781 119 : log_printinfo(store->logger);
7782 119 : MT_lock_unset(&store->commit);
7783 : }
|