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