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