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