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 - 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 :
15 : #include "rel_tvtree.h"
16 : #include "rel_exp.h"
17 : #include "rel_bin.h"
18 : #include "sql_statement.h"
19 :
20 : static tv_type
21 139546 : tv_get_type(sql_subtype *st)
22 : {
23 139546 : if (st->multiset) {
24 26 : if (st->multiset == MS_ARRAY)
25 : return TV_MSET;
26 0 : if (st->multiset == MS_SETOF)
27 0 : return TV_SETOF;
28 139520 : } else if (st->type->composite)
29 16 : return TV_COMP;
30 :
31 : return TV_BASIC;
32 : }
33 :
34 : static tv_tree*
35 139518 : tv_node(allocator *sa, sql_subtype *st, tv_type tvt)
36 : {
37 139518 : tv_tree *n = (sa)?SA_NEW(sa, tv_tree):MNEW(tv_tree);
38 139400 : if (n == NULL)
39 : return NULL;
40 139400 : n->st = st;
41 139400 : n->tvt = tvt;
42 139400 : n->rid_idx = 0;
43 139400 : n->ctl = n->rid = n->msid = n->msnr = n->vals = NULL;
44 :
45 : /* allocate only the lists that we need based on the tv-tree type */
46 139400 : switch (n->tvt) {
47 139345 : case TV_BASIC:
48 139345 : n->vals = sa_list(sa);
49 139380 : return n;
50 29 : case TV_COMP:
51 29 : n->ctl = sa_list(sa);
52 87 : for (node *sf = st->type->d.fields->h; sf; sf = sf->next) {
53 58 : sql_arg *sfa = sf->data;
54 58 : append(n->ctl, tv_node(sa, &sfa->type, tv_get_type(&sfa->type)));
55 : }
56 : return n;
57 26 : case TV_MSET:
58 26 : n->msnr = sa_list(sa);
59 : /* fall through */
60 26 : case TV_SETOF:
61 26 : n->rid = sa_list(sa);
62 26 : n->msid = sa_list(sa);
63 26 : n->ctl = sa_list(sa);
64 :
65 : /* For MSET/SETOF we make a new child node for the values
66 : * NOTE: the ->st of the child is the same as this node so
67 : * we need to **EXPLICITLY** specify the tv_type */
68 26 : tv_tree *sn;
69 26 : if (st->type->composite)
70 13 : sn = tv_node(sa, st, TV_COMP);
71 : else
72 13 : sn = tv_node(sa, st, TV_BASIC);
73 26 : sn->st = st;
74 :
75 26 : append(n->ctl, sn);
76 :
77 26 : return n;
78 : default:
79 0 : assert(0);
80 : break;
81 : }
82 :
83 : return NULL;
84 : }
85 :
86 : tv_tree *
87 139468 : tv_create(backend *be, sql_subtype *st)
88 : {
89 : /* there is some ambiguity with the types-value tree construction:
90 : * nodes which are mset/setof have their underlying type (composite/basic)
91 : * in the same subtype->type struct. That's why we have to be careful
92 : * with how we generate the nodes. Read carefully tv_node */
93 139468 : return tv_node(be->mvc->sa, st, tv_get_type(st));
94 : }
95 :
96 : static bool
97 : tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt *sel);
98 :
99 : static int
100 62 : append_values_from_varchar(backend *be, tv_tree *t, stmt *sl, stmt *left, stmt *sel)
101 : {
102 62 : node *n, *m;
103 62 : int sid = 0;
104 :
105 62 : switch(t->tvt) {
106 30 : case TV_BASIC:
107 30 : assert(sl->type == st_result || sl->type == st_list);
108 :
109 30 : if (sl->type == st_result)
110 20 : list_append(t->vals, sl);
111 10 : else if (sl->type == st_list) {
112 10 : stmt *sa = sl->op4.lval->h->data;
113 10 : list_append(t->vals, sa->op1);
114 : }
115 : return 1;
116 14 : case TV_COMP:
117 42 : for (n = t->ctl->h, m = sl->op4.lval->h; n; n = n->next, m = m->next) {
118 28 : stmt *ts = m->data;
119 28 : assert(ts->type == st_alias);
120 28 : append_values_from_varchar(be, n->data, ts->op1, left, sel);
121 : }
122 14 : return list_length(t->ctl);
123 18 : case TV_MSET:
124 : case TV_SETOF:
125 18 : assert(list_length(t->ctl) == 1);
126 :
127 18 : sid = append_values_from_varchar(be, t->ctl->h->data, sl, left, sel);
128 :
129 18 : list_append(t->msid, list_fetch(sl->op4.lval, sid++));
130 18 : if (t->tvt == TV_MSET)
131 18 : list_append(t->msnr, list_fetch(sl->op4.lval, sid++));
132 18 : list_append(t->rid, list_fetch(sl->op4.lval, sid++));
133 :
134 18 : assert(list_length(sl->op4.lval) == sid);
135 :
136 : return sid;
137 : default:
138 0 : assert(0);
139 : break;
140 : }
141 : return 0;
142 : }
143 :
144 : static bool
145 35 : mset_value_from_array_constructor(backend *be, tv_tree *t, sql_exp *values, stmt *left, stmt *sel)
146 : {
147 : /* rowid */
148 35 : stmt *rid = stmt_atom_int(be, t->rid_idx);
149 35 : if (!rid)
150 : return false;
151 35 : assert(t->rid);
152 35 : list_append(t->rid, rid);
153 :
154 : /* per value insert actual data, msid(=rowid), msnr(for MSET only) */
155 35 : int msnr_idx = 1; /* NOTE: in mset-value values are 1-offset indexed */
156 35 : list *ms_vals = values->f;
157 102 : for (node *n = ms_vals->h; n; n = n->next, msnr_idx++) {
158 :
159 : /* vals (in the child tree) */
160 67 : assert(list_length(t->ctl) == 1);
161 67 : tv_tree *ct = t->ctl->h->data;
162 67 : tv_parse_values_(be, ct, n->data, left, sel);
163 :
164 : /* msid */
165 67 : stmt *msid = stmt_atom_int(be, t->rid_idx);
166 67 : if (!msid)
167 : return false;
168 67 : list_append(t->msid, msid);
169 :
170 : /* msnr */
171 67 : if (t->tvt == TV_MSET) {
172 67 : stmt *msnr = stmt_atom_int(be, msnr_idx);
173 67 : if (!msnr)
174 : return false;
175 67 : list_append(t->msnr, msnr);
176 : }
177 : }
178 :
179 : /* we inserted all the mset-value's subvalues so now
180 : * increment this tv_tree node's (mset) rowid index */
181 35 : t->rid_idx++;
182 :
183 35 : return true;
184 : }
185 :
186 : static bool
187 10 : mset_value_from_literal(backend *be, tv_tree *t, sql_exp *values, stmt *left, stmt *sel)
188 : {
189 : /* per entry-value in the literal the call to exp_bin() will generate an
190 : * `sql.from_varchar()` instruction. This instructions for a given returns
191 : * either 3 or 4 bat results corresponding to rowid, value, msid and optionally
192 : * msnr (multiset vs setof). Those return values will be in an st_list stmt
193 : * so we have to retrieve them (from stmt_list's op4) and append them to the
194 : * tv_tree list of stmts */
195 10 : assert(t->tvt == TV_SETOF || t->tvt == TV_MSET);
196 10 : assert(!t->vals && t->ctl);
197 :
198 10 : stmt *i = exp_bin(be, values, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
199 10 : if (!i)
200 : return false;
201 :
202 10 : assert(i->type == st_list);
203 :
204 10 : append_values_from_varchar(be, t, i, left, sel);
205 :
206 10 : return true;
207 : }
208 :
209 : static bool
210 51 : comp_value_from_parenthesis(backend *be, tv_tree *t, sql_exp *values, stmt *left, stmt *sel)
211 : {
212 51 : assert(values->f);
213 51 : list *ct_vals = values->f;
214 :
215 51 : int cnt = 0;
216 153 : for (node *n = ct_vals->h; n; cnt++, n = n->next)
217 102 : if (false == tv_parse_values_(be, list_fetch(t->ctl, cnt), n->data, left, sel))
218 : return false;
219 :
220 : return true;
221 : }
222 :
223 : static bool
224 6 : comp_value_from_literal(backend *be, tv_tree *t, sql_exp *values, stmt *left, stmt *sel)
225 : {
226 6 : assert(t->tvt == TV_COMP);
227 6 : assert(!t->vals && t->ctl);
228 :
229 6 : stmt *i = exp_bin(be, values, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
230 6 : if (!i)
231 : return false;
232 :
233 6 : append_values_from_varchar(be, t, i, left, sel);
234 :
235 6 : return true;
236 : }
237 :
238 : static bool
239 748790 : tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt *sel)
240 : {
241 748790 : stmt *i;
242 748790 : sql_exp* uc;
243 :
244 748790 : switch (t->tvt) {
245 748688 : case TV_BASIC:
246 748688 : i = exp_bin(be, value, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
247 749680 : if (!i)
248 : return false;
249 749680 : assert(t->vals);
250 749680 : list_append(t->vals, i);
251 749680 : break;
252 45 : case TV_MSET:
253 : case TV_SETOF:
254 : //assert(is_convert(value->type));
255 45 : assert(value->f);
256 45 : uc = value;
257 45 : if (is_convert(value->type))
258 44 : uc = value->l;
259 45 : if (!uc->f)
260 : /* VALUES ('{1, 2, 3}') */
261 10 : return mset_value_from_literal(be, t, value, left, sel);
262 : else
263 : /* VALUES (array[1, 2, 3]) */
264 35 : return mset_value_from_array_constructor(be, t, uc, left, sel);
265 57 : break;
266 57 : case TV_COMP:
267 57 : if (is_convert(value->type))
268 : /* VALUES ('(1,"alice")') */
269 6 : return comp_value_from_literal(be, t, value, left, sel);
270 : else
271 : /* VALUES ((1,'alice')) */
272 51 : return comp_value_from_parenthesis(be, t, value, left, sel);
273 0 : break;
274 : default:
275 0 : assert(0);
276 : break;
277 : }
278 :
279 749680 : return true;
280 : }
281 :
282 : static inline sql_exp *
283 6 : tv_exp_wrap_list(backend *be, tv_tree *t, list *l)
284 : {
285 12 : sql_exp *e = exp_null(be->mvc->sa, t->st);
286 6 : e->l = e->f = 0;
287 6 : e->f = l;
288 6 : return e;
289 : }
290 :
291 : bool
292 137292 : tv_parse_values(backend *be, tv_tree *t, sql_exp *col_vals, stmt *left, stmt *sel)
293 : {
294 137292 : list *vals = exp_get_values(col_vals);
295 : /* vals is a list with values that correspond to a column whose
296 : * (possibly "complex") type is represented by the tv_tree. NOTE:
297 : * in this case vals might be either
298 : * 1. a list of many values or
299 : * 2. a single value of composite or mset/setof with composite/basic type.
300 : * that's why we need to check for
301 : * a. ->row in the first entry of col_vals exp
302 : * b. for mset/setof the first ->row in the first entry of vals
303 : * If it is set it means that we are dealing with a single row insert and we
304 : * need a dummy expression de (to put vals at its e->f) so parsing the values
305 : * stays similar with the general case
306 : */
307 137425 : bool single_row_val = false;
308 137425 : single_row_val |= col_vals->row;
309 137425 : if ((t->tvt == TV_MSET) || (t->tvt == TV_SETOF)) {
310 : // single value MSET/SETOF of basic type
311 10 : single_row_val |= !((sql_exp*)vals->h->data)->f;
312 : // single value MSET/SETOF of composite type
313 10 : single_row_val |= ((sql_exp*)vals->h->data)->row;
314 : }
315 :
316 137425 : if (single_row_val) {
317 : /* we need to create a dummy expression to single row vals
318 : * to adhere to the rest of the api */
319 6 : sql_exp *de = tv_exp_wrap_list(be, t, vals);
320 6 : if (false == tv_parse_values_(be, t, de, left, sel))
321 : return false;
322 : } else {
323 886455 : for (node *n = vals->h; n; n = n->next) {
324 748814 : sql_exp *e = n->data;
325 748814 : if (false == tv_parse_values_(be, t, e, left, sel))
326 : return false;
327 : }
328 : }
329 : return true;
330 : }
331 :
332 : stmt *
333 137378 : tv_generate_stmts(backend *be, tv_tree *t)
334 : {
335 137378 : stmt *ap, *tmp, *s;
336 137378 : list *sl;
337 :
338 137378 : switch (t->tvt) {
339 137323 : case TV_BASIC:
340 137323 : return stmt_append_bulk(be, stmt_temp(be, t->st), t->vals);
341 26 : case TV_MSET:
342 : case TV_SETOF:
343 : /* vals (in the child tree) */
344 26 : assert(list_length(t->ctl) == 1);
345 26 : tv_tree *ct = t->ctl->h->data;
346 26 : tmp = tv_generate_stmts(be, ct);
347 :
348 : /* if the lower tv node does NOT returns a list (e.g. because
349 : * it is basic type) we need to create it explicitly */
350 26 : if (tmp->type == st_list) {
351 : s = tmp;
352 : } else {
353 13 : s = stmt_list(be, sa_list(be->mvc->sa));
354 13 : list_append(s->op4.lval, tmp);
355 : }
356 :
357 : /* msid */
358 26 : tmp = stmt_temp(be, tail_type(t->msid->h->data));
359 26 : ap = stmt_append_bulk(be, tmp, t->msid);
360 26 : append(s->op4.lval, ap);
361 :
362 : /* msnr */
363 26 : if (t->tvt == TV_MSET) {
364 26 : tmp = stmt_temp(be, tail_type(t->msnr->h->data));
365 26 : ap = stmt_append_bulk(be, tmp, t->msnr);
366 26 : append(s->op4.lval, ap);
367 : }
368 :
369 : /* rid */
370 26 : tmp = stmt_temp(be, tail_type(t->rid->h->data));
371 26 : ap = stmt_append_bulk(be, tmp, t->rid);
372 26 : append(s->op4.lval, ap);
373 :
374 : /* we've appended in the stmt_list so update nrcols */
375 26 : stmt_set_nrcols(s);
376 26 : s->subtype = *t->st;
377 26 : return s;
378 29 : case TV_COMP:
379 29 : sl = sa_list(be->mvc->sa);
380 : /* gather all the composite (sub)field's statements */
381 87 : for (node *n = t->ctl->h; n; n = n->next)
382 58 : list_append(sl, tv_generate_stmts(be, n->data));
383 29 : return stmt_list(be, sl);
384 : default:
385 0 : assert(0);
386 : return NULL;
387 : }
388 : return s;
389 : }
|