Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "sql_catalog.h"
15 : #include "sql_storage.h"
16 :
17 : const char *TID = "%TID%";
18 :
19 : inline int
20 1267872 : base_key( sql_base *b )
21 : {
22 1267872 : return hash_key(b->name);
23 : }
24 :
25 : void
26 549534 : trans_add(sql_trans *tr, sql_base *b, void *data, tc_cleanup_fptr cleanup, tc_commit_fptr commit, tc_log_fptr log)
27 : {
28 549534 : sql_change *change = MNEW(sql_change);
29 :
30 549533 : *change = (sql_change) {
31 : .obj = b,
32 : .data = data,
33 : .cleanup = cleanup,
34 : .commit = commit,
35 : .log = log,
36 : };
37 549533 : MT_lock_set(&tr->lock);
38 549509 : tr->changes = list_add(tr->changes, change);
39 549525 : if (log)
40 259237 : tr->logchanges++;
41 549525 : MT_lock_unset(&tr->lock);
42 549509 : }
43 :
44 : void
45 7 : trans_del(sql_trans *tr, sql_base *b)
46 : {
47 7 : MT_lock_set(&tr->lock);
48 68 : for(node *n= tr->changes->h; n; n = n->next) {
49 61 : sql_change *c = n->data;
50 61 : if (c->obj == b) {
51 1 : if (c->log)
52 1 : tr->logchanges--;
53 1 : _DELETE(c);
54 1 : n = list_remove_node(tr->changes, NULL, n);
55 : }
56 : }
57 7 : MT_lock_unset(&tr->lock);
58 7 : }
59 :
60 : int
61 5683 : tr_version_of_parent(sql_trans *tr, ulng ts)
62 : {
63 10483 : for( tr = tr->parent; tr; tr = tr->parent)
64 7407 : if (tr->tid == ts)
65 : return 1;
66 : return 0;
67 : }
68 :
69 : node *
70 105 : list_find_name(list *l, const char *name)
71 : {
72 105 : node *n;
73 :
74 105 : if (l)
75 320 : for (n = l->h; n; n = n->next) {
76 314 : sql_base *b = n->data;
77 :
78 : /* check if names match */
79 314 : if (name[0] == b->name[0] && strcmp(name, b->name) == 0) {
80 99 : return n;
81 : }
82 : }
83 : return NULL;
84 : }
85 :
86 : node *
87 0 : cs_find_id(changeset * cs, sqlid id)
88 : {
89 0 : node *n;
90 0 : list *l = cs->set;
91 :
92 0 : if (l)
93 0 : for (n = l->h; n; n = n->next) {
94 0 : sql_base *b = n->data;
95 :
96 : /* check if names match */
97 0 : if (b->id == id) {
98 0 : return n;
99 : }
100 : }
101 : return NULL;
102 : }
103 :
104 : node *
105 837 : list_find_id(list *l, sqlid id)
106 : {
107 837 : if (l) {
108 835 : node *n;
109 10425 : for (n = l->h; n; n = n->next) {
110 :
111 : /* check if ids match */
112 9597 : if (id == *(sqlid *) n->data) {
113 7 : return n;
114 : }
115 : }
116 : }
117 : return NULL;
118 : }
119 :
120 : node *
121 0 : list_find_base_id(list *l, sqlid id)
122 : {
123 0 : if (l) {
124 0 : node *n;
125 0 : for (n = l->h; n; n = n->next) {
126 0 : sql_base *b = n->data;
127 :
128 0 : if (id == b->id)
129 0 : return n;
130 : }
131 : }
132 : return NULL;
133 : }
134 :
135 : sql_key *
136 483 : find_sql_key(sql_table *t, const char *kname)
137 : {
138 483 : node *n = ol_find_name(t->keys, kname);
139 483 : if (n)
140 0 : return n->data;
141 : return NULL;
142 : }
143 :
144 : sql_key *
145 278 : sql_trans_find_key(sql_trans *tr, sqlid id)
146 : {
147 278 : struct os_iter oi;
148 278 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
149 278 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
150 278 : sql_schema *s = (sql_schema*)b;
151 278 : sql_base *bk = os_find_id(s->keys, tr, id);
152 278 : if (bk)
153 278 : return (sql_key*)bk;
154 : }
155 : return NULL;
156 : }
157 :
158 : sql_key *
159 7308 : schema_find_key(sql_trans *tr, sql_schema *s, const char *name)
160 : {
161 7308 : sql_base *b = os_find_name(s->keys, tr, name);
162 :
163 7308 : if (!b && tr->tmp == s) {
164 92 : struct os_iter oi;
165 92 : os_iterator(&oi, tr->localtmps, tr, NULL);
166 575 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
167 483 : sql_table *t = (sql_table *) b;
168 483 : sql_key *o = find_sql_key(t, name);
169 483 : if (o)
170 0 : return o;
171 : }
172 : }
173 : return (sql_key*)b;
174 : }
175 :
176 : sql_idx *
177 10544 : find_sql_idx(sql_table *t, const char *iname)
178 : {
179 10544 : node *n = ol_find_name(t->idxs, iname);
180 10544 : if (n)
181 4021 : return n->data;
182 : return NULL;
183 : }
184 :
185 : sql_idx *
186 8 : sql_trans_find_idx(sql_trans *tr, sqlid id)
187 : {
188 8 : struct os_iter oi;
189 8 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
190 8 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
191 8 : sql_schema *s = (sql_schema*)b;
192 8 : sql_base *bi = os_find_id(s->idxs, tr, id);
193 8 : if (bi)
194 8 : return (sql_idx*)bi;
195 : }
196 : return NULL;
197 : }
198 :
199 : sql_idx *
200 19780 : schema_find_idx(sql_trans *tr, sql_schema *s, const char *name)
201 : {
202 19780 : sql_base *b = os_find_name(s->idxs, tr, name);
203 :
204 19777 : if (!b && tr->tmp == s) {
205 306 : struct os_iter oi;
206 306 : os_iterator(&oi, tr->localtmps, tr, NULL);
207 1080 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
208 809 : sql_table *t = (sql_table *) b;
209 809 : sql_idx *o = find_sql_idx(t, name);
210 809 : if (o)
211 35 : return o;
212 : }
213 : }
214 : return (sql_idx*)b;
215 : }
216 :
217 : sql_idx *
218 1168 : schema_find_idx_id(sql_trans *tr, sql_schema *s, sqlid id)
219 : {
220 1168 : sql_base *b = os_find_id(s->idxs, tr, id);
221 :
222 1168 : if (!b && tr->tmp == s) {
223 24 : struct os_iter oi;
224 24 : os_iterator(&oi, tr->localtmps, tr, NULL);
225 122 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
226 122 : sql_table *t = (sql_table *) b;
227 122 : node *o = ol_find_id(t->idxs, id);
228 122 : if (o)
229 24 : return (sql_idx*)o->data;
230 : }
231 : }
232 : return (sql_idx*)b;
233 : }
234 :
235 :
236 : sql_column *
237 9189591 : find_sql_column(sql_table *t, const char *cname)
238 : {
239 9189591 : node *n = ol_find_name(t->columns, cname);
240 9188871 : if (n)
241 8924115 : return n->data;
242 : return NULL;
243 : }
244 :
245 : sql_table *
246 6760586 : find_sql_table(sql_trans *tr, sql_schema *s, const char *tname)
247 : {
248 6760586 : sql_table *t = (sql_table*)os_find_name(s->tables, tr, tname);
249 :
250 6760960 : if (!t && tr->tmp == s) {
251 212881 : t = (sql_table*) os_find_name(tr->localtmps, tr, tname);
252 212881 : return t;
253 : }
254 :
255 6482979 : if (t && isTempTable(t) && tr->tmp == s) {
256 65158 : sqlstore *store = tr->store;
257 65158 : assert(isGlobal(t));
258 :
259 65158 : sql_table* lt = (sql_table*) os_find_name(tr->localtmps, tr, tname);
260 65157 : if (lt)
261 : return lt;
262 4439 : MT_lock_set(&store->table_locks[t->base.id&(NR_TABLE_LOCKS-1)]);
263 :
264 4439 : lt = (sql_table*) os_find_name(tr->localtmps, tr, tname);
265 4439 : if (!lt)
266 4436 : t = globaltmp_instantiate(tr, t);
267 : else
268 : t = lt;
269 4439 : MT_lock_unset(&store->table_locks[t->base.id&(NR_TABLE_LOCKS-1)]);
270 4439 : return t;
271 : }
272 :
273 : return t;
274 : }
275 :
276 : sql_table *
277 38297 : find_sql_table_id(sql_trans *tr, sql_schema *s, sqlid id)
278 : {
279 38297 : sql_table *t = (sql_table*)os_find_id(s->tables, tr, id);
280 38297 : if (!t && tr->tmp == s) {
281 59 : t = (sql_table*) os_find_id(tr->localtmps, tr, id);
282 59 : return t;
283 : }
284 :
285 38238 : if (t && isTempTable(t) && tr->tmp == s) {
286 52 : sqlstore *store = tr->store;
287 52 : assert(isGlobal(t));
288 :
289 52 : sql_table* lt = (sql_table*) os_find_id(tr->localtmps, tr, id);
290 52 : if (lt)
291 : return lt;
292 0 : MT_lock_set(&store->table_locks[id&(NR_TABLE_LOCKS-1)]);
293 0 : lt = (sql_table*) os_find_id(tr->localtmps, tr, id);
294 0 : if (!lt)
295 0 : t = globaltmp_instantiate(tr, t);
296 : else
297 : t = lt;
298 0 : MT_lock_unset(&store->table_locks[id&(NR_TABLE_LOCKS-1)]);
299 0 : return t;
300 : }
301 : return t;
302 : }
303 :
304 : sql_table *
305 238 : sql_trans_find_table(sql_trans *tr, sqlid id)
306 : {
307 238 : struct os_iter oi;
308 238 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
309 400 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
310 400 : sql_schema *s = (sql_schema*)b;
311 400 : sql_base *bt = os_find_id(s->tables, tr, id);
312 400 : if (bt)
313 238 : return (sql_table*)bt;
314 : }
315 : return NULL;
316 : }
317 :
318 : sql_sequence *
319 3655 : find_sql_sequence(sql_trans *tr, sql_schema *s, const char *sname)
320 : {
321 3655 : return (sql_sequence*)os_find_name(s->seqs, tr, sname);
322 : }
323 :
324 : sql_schema *
325 9800445 : find_sql_schema(sql_trans *tr, const char *sname)
326 : {
327 9800445 : if (tr->tmp && strcmp(sname, "tmp")==0)
328 : return tr->tmp;
329 9188092 : return (sql_schema*)os_find_name(tr->cat->schemas, tr, sname);
330 : }
331 :
332 : sql_schema *
333 1768 : find_sql_schema_id(sql_trans *tr, sqlid id)
334 : {
335 1768 : if (tr->tmp && tr->tmp->base.id == id)
336 : return tr->tmp;
337 1442 : return (sql_schema*)os_find_id(tr->cat->schemas, tr, id);
338 : }
339 :
340 : sql_type *
341 60981 : find_sql_type(sql_trans *tr, sql_schema *s, const char *tname)
342 : {
343 60981 : return (sql_type*)os_find_name(s->types, tr, tname);
344 : }
345 :
346 : sql_type *
347 49088 : sql_trans_bind_type(sql_trans *tr, sql_schema *c, const char *name)
348 : {
349 49088 : struct os_iter oi;
350 49088 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
351 50635 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
352 50414 : sql_schema *s = (sql_schema*)b;
353 50414 : sql_type *t = find_sql_type(tr, s, name);
354 50414 : if (t)
355 48867 : return t;
356 : }
357 221 : if (c)
358 0 : return find_sql_type(tr, c, name);
359 : return NULL;
360 : }
361 :
362 : sql_type *
363 3 : sql_trans_find_type(sql_trans *tr, sql_schema *s, sqlid id)
364 : {
365 3 : if (s) {
366 3 : sql_base *b = os_find_id(s->types, tr, id);
367 3 : if (b)
368 : return (sql_type*)b;
369 : } else {
370 0 : struct os_iter oi;
371 0 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
372 0 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
373 0 : sql_schema *s = (sql_schema*)b;
374 0 : sql_base *bt = os_find_id(s->types, tr, id);
375 0 : if (bt)
376 0 : return (sql_type*)bt;
377 : }
378 : }
379 : return NULL;
380 : }
381 :
382 : sql_func *
383 389 : sql_trans_find_func(sql_trans *tr, sqlid id)
384 : {
385 389 : struct os_iter oi;
386 389 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
387 601 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
388 596 : sql_schema *s = (sql_schema*)b;
389 596 : sql_base *bf = os_find_id(s->funcs, tr, id);
390 596 : if (bf)
391 384 : return (sql_func*)bf;
392 : }
393 : return NULL;
394 : }
395 :
396 : static sql_trigger *
397 93 : find_sql_trigger(sql_table *t, const char *tname)
398 : {
399 93 : node *n = ol_find_name(t->triggers, tname);
400 93 : if (n)
401 0 : return n->data;
402 : return NULL;
403 : }
404 :
405 : sql_trigger *
406 2 : sql_trans_find_trigger(sql_trans *tr, sqlid id)
407 : {
408 2 : struct os_iter oi;
409 2 : os_iterator(&oi, tr->cat->schemas, tr, NULL);
410 2 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
411 2 : sql_schema *s = (sql_schema*)b;
412 2 : sql_base *bt = os_find_id(s->triggers, tr, id);
413 2 : if (bt)
414 2 : return (sql_trigger*)bt;
415 : }
416 : return NULL;
417 : }
418 :
419 : sql_trigger *
420 950 : schema_find_trigger(sql_trans *tr, sql_schema *s, const char *name)
421 : {
422 950 : sql_base *b = os_find_name(s->triggers, tr, name);
423 :
424 950 : if (!b && tr->tmp == s) {
425 95 : struct os_iter oi;
426 95 : os_iterator(&oi, tr->localtmps, tr, NULL);
427 188 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
428 93 : sql_table *t = (sql_table *) b;
429 93 : sql_trigger *o = find_sql_trigger(t, name);
430 93 : if (o)
431 0 : return o;
432 : }
433 : }
434 : return (sql_trigger*)b;
435 : }
436 :
437 : void*
438 197 : sql_values_list_element_validate_and_insert(void *v1, void *v2, void *tpe, int* res)
439 : {
440 197 : sql_part_value* pt = (sql_part_value*) v1, *newp = (sql_part_value*) v2;
441 197 : sql_subtype *tp = (sql_subtype *) tpe;
442 :
443 197 : *res = ATOMcmp(tp->type->localtype, newp->value, pt->value);
444 197 : return *res == 0 ? pt : NULL;
445 : }
446 :
447 : void*
448 131 : sql_range_part_validate_and_insert(void *v1, void *v2, void *type)
449 : {
450 131 : sql_part* pt = (sql_part*) v1, *newp = (sql_part*) v2;
451 131 : int res1, res2, tpe = *(int*)type;
452 131 : const void *nil = ATOMnilptr(tpe);
453 131 : bool pt_down_all = false, pt_upper_all = false, newp_down_all = false, newp_upper_all = false, pt_min_max_same = false, newp_min_max_same = false;
454 :
455 131 : if (pt == newp) /* same pointer, skip (used in updates) */
456 : return NULL;
457 :
458 128 : if (is_bit_nil(pt->with_nills) || is_bit_nil(newp->with_nills)) /* if one partition holds all including nills, then conflicts */
459 : return pt;
460 124 : if (newp->with_nills && pt->with_nills) /* only one partition at most has null values */
461 : return pt;
462 :
463 118 : pt_down_all = !ATOMcmp(tpe, nil, pt->part.range.minvalue);
464 118 : pt_upper_all = !ATOMcmp(tpe, nil, pt->part.range.maxvalue);
465 118 : newp_down_all = !ATOMcmp(tpe, nil, newp->part.range.minvalue);
466 118 : newp_upper_all = !ATOMcmp(tpe, nil, newp->part.range.maxvalue);
467 :
468 : /* if one partition just holds NULL values, then there's no conflict */
469 118 : if ((newp_down_all && newp_upper_all && newp->with_nills) || (pt_down_all && pt_upper_all && pt->with_nills))
470 : return NULL;
471 : /* holds all range, will always conflict */
472 102 : if ((pt_down_all && pt_upper_all && !pt->with_nills) || (newp_down_all && newp_upper_all && !newp->with_nills))
473 : return pt;
474 :
475 98 : pt_min_max_same = !ATOMcmp(tpe, pt->part.range.maxvalue, pt->part.range.minvalue);
476 98 : newp_min_max_same = !ATOMcmp(tpe, newp->part.range.maxvalue, newp->part.range.minvalue);
477 :
478 98 : if (pt_down_all) { /* from range min value until a value */
479 23 : res1 = ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue);
480 23 : if (newp_down_all || (!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0))
481 : return pt;
482 : return NULL;
483 : }
484 75 : if (pt_upper_all) { /* from value until range max value */
485 9 : res1 = ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue);
486 9 : if (newp_upper_all || (!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0))
487 : return pt;
488 : return NULL;
489 : }
490 66 : if (newp_down_all) { /* from range min value until a value */
491 2 : res1 = ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue);
492 2 : if (pt_down_all || (!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0))
493 : return pt;
494 : return NULL;
495 : }
496 64 : if (newp_upper_all) { /* from value until range max value */
497 15 : res1 = ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue);
498 15 : if (pt_upper_all || (!pt_min_max_same && res1 > 0) || (pt_min_max_same && res1 >= 0))
499 : return pt;
500 : return NULL;
501 : }
502 :
503 : /* Fallback into normal cases */
504 49 : res1 = ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue);
505 49 : res2 = ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue);
506 : /* overlap: y2 > x1 && x2 > y1 */
507 49 : if (((!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0)) && ((!pt_min_max_same && res2 > 0) || (pt_min_max_same && res2 >= 0)))
508 : return pt;
509 : return NULL;
510 : }
511 :
512 : void*
513 44 : sql_values_part_validate_and_insert(void *v1, void *v2, void *type)
514 : {
515 44 : sql_part* pt = (sql_part*) v1, *newp = (sql_part*) v2;
516 44 : list* b1 = pt->part.values, *b2 = newp->part.values;
517 44 : node *n1 = b1->h, *n2 = b2->h;
518 44 : int res, tpe = *(int*)type;
519 :
520 44 : if (pt == newp) /* same pointer, skip (used in updates) */
521 : return NULL;
522 :
523 42 : if (newp->with_nills && pt->with_nills)
524 : return pt; /* check for nulls first */
525 :
526 145 : while (n1 && n2) {
527 108 : sql_part_value *p1 = (sql_part_value *) n1->data, *p2 = (sql_part_value *) n2->data;
528 108 : res = ATOMcmp(tpe, p1->value, p2->value);
529 108 : if (!res) { /* overlap -> same value in both partitions */
530 : return pt;
531 104 : } else if (res < 0) {
532 101 : n1 = n1->next;
533 : } else {
534 3 : n2 = n2->next;
535 : }
536 : }
537 : return NULL;
538 : }
539 :
540 : sql_part *
541 786980 : partition_find_part(sql_trans *tr, sql_table *pt, sql_part *pp)
542 : {
543 786980 : struct os_iter oi;
544 :
545 786980 : if (!pt->s) /* declared table */
546 : return NULL;
547 786971 : os_iterator(&oi, pt->s->parts, tr, NULL);
548 818332 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
549 34683 : sql_part *p = (sql_part*)b;
550 :
551 34683 : if (pp) {
552 123 : if (p == pp)
553 18 : pp = NULL;
554 123 : continue;
555 : }
556 34560 : if (p->member == pt->base.id)
557 3326 : return p;
558 : }
559 : return NULL;
560 : }
561 :
562 : node *
563 953 : members_find_child_id(list *l, sqlid id)
564 : {
565 953 : if (l) {
566 953 : node *n;
567 1355 : for (n = l->h; n; n = n->next) {
568 777 : sql_part *p = n->data;
569 :
570 777 : if (id == p->member)
571 375 : return n;
572 : }
573 : }
574 : return NULL;
575 : }
576 :
577 : int
578 583 : nested_mergetable(sql_trans *tr, sql_table *mt, const char *sname, const char *tname)
579 : {
580 583 : if (strcmp(mt->s->base.name, sname) == 0 && strcmp(mt->base.name, tname) == 0)
581 : return 1;
582 : /* try if this is also a partition */
583 599 : for( sql_part *parent = partition_find_part(tr, mt, NULL); parent; parent = partition_find_part(tr, mt, parent)) {
584 21 : if (nested_mergetable(tr, parent->t, sname, tname))
585 : return 1;
586 : }
587 : return 0;
588 : }
589 :
590 : bool
591 3899060 : is_column_unique(sql_column *c)
592 : {
593 : /* is it a primary key column itself? */
594 3899060 : if (c->t->pkey && list_length(c->t->pkey->k.columns) == 1 &&
595 400929 : ((sql_kc*)c->t->pkey->k.columns->h->data)->c->base.id == c->base.id)
596 : return true;
597 : /* is it a unique key itself */
598 3757861 : return c->unique == 2;
599 : }
600 :
601 : ValPtr
602 6270521 : SA_VALcopy(allocator *sa, ValPtr d, const ValRecord *s)
603 : {
604 6270521 : if (sa == NULL)
605 1819 : return VALcopy(d, s);
606 6268702 : if (!ATOMextern(s->vtype)) {
607 4499678 : *d = *s;
608 1769024 : } else if (s->val.pval == 0) {
609 0 : const void *p = ATOMnilptr(s->vtype);
610 0 : d->vtype = s->vtype;
611 0 : d->len = ATOMlen(d->vtype, p);
612 0 : d->val.pval = sa_alloc(sa, d->len);
613 0 : if (d->val.pval == NULL)
614 : return NULL;
615 0 : memcpy(d->val.pval, p, d->len);
616 1769024 : } else if (s->vtype == TYPE_str) {
617 1768738 : const char *p = s->val.sval;
618 1768738 : d->vtype = TYPE_str;
619 1768738 : d->len = strLen(p);
620 1768738 : d->val.sval = sa_alloc(sa, d->len);
621 1768738 : if (d->val.sval == NULL)
622 : return NULL;
623 1768738 : memcpy(d->val.sval, p, d->len);
624 : } else {
625 286 : const void *p = s->val.pval;
626 286 : d->vtype = s->vtype;
627 286 : d->len = ATOMlen(d->vtype, p);
628 286 : d->val.pval = sa_alloc(sa, d->len);
629 286 : if (d->val.pval == NULL)
630 : return NULL;
631 286 : memcpy(d->val.pval, p, d->len);
632 : }
633 : return d;
634 : }
635 :
636 : atom *
637 261669 : atom_copy(allocator *sa, atom *a)
638 : {
639 261669 : atom *r = sa ?SA_NEW(sa, atom):MNEW(atom);
640 261669 : if (!r)
641 : return NULL;
642 :
643 261669 : *r = (atom) {
644 261669 : .isnull = a->isnull,
645 261669 : .tpe = a->tpe,
646 : .data = (ValRecord) {.vtype = TYPE_void,},
647 : };
648 261669 : if (!a->isnull)
649 260566 : SA_VALcopy(sa, &r->data, &a->data);
650 : return r;
651 : }
652 :
653 :
654 : sql_table*
655 0 : find_sys_table(sql_trans *tr, const char* tbl_name)
656 : {
657 0 : sql_schema *sys = find_sql_schema(tr, "sys");
658 0 : return find_sql_table(tr, sys, tbl_name);
659 : }
|