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