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