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