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