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