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 139541 : tv_get_type(sql_subtype *st)
22 : {
23 139541 : if (st->multiset) {
24 30 : if (st->multiset == MS_ARRAY)
25 : return TV_MSET;
26 0 : if (st->multiset == MS_SETOF)
27 0 : return TV_SETOF;
28 139511 : } else if (st->type->composite)
29 18 : return TV_COMP;
30 :
31 : return TV_BASIC;
32 : }
33 :
34 : static tv_tree*
35 139512 : tv_node(allocator *sa, sql_subtype *st, tv_type tvt)
36 : {
37 139512 : tv_tree *n = (sa)?SA_NEW(sa, tv_tree):MNEW(tv_tree);
38 139415 : if (n == NULL)
39 : return NULL;
40 139415 : n->st = st;
41 139415 : n->tvt = tvt;
42 139415 : n->rid_idx = 0;
43 139415 : 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 139415 : switch (n->tvt) {
47 139351 : case TV_BASIC:
48 139351 : n->vals = sa_list(sa);
49 139359 : return n;
50 34 : case TV_COMP:
51 34 : n->ctl = sa_list(sa);
52 102 : for (node *sf = st->type->d.fields->h; sf; sf = sf->next) {
53 68 : sql_arg *sfa = sf->data;
54 68 : append(n->ctl, tv_node(sa, &sfa->type, tv_get_type(&sfa->type)));
55 : }
56 : return n;
57 30 : case TV_MSET:
58 30 : n->msnr = sa_list(sa);
59 : /* fall through */
60 30 : case TV_SETOF:
61 30 : n->rid = sa_list(sa);
62 30 : n->msid = sa_list(sa);
63 30 : 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 30 : tv_tree *sn;
69 30 : if (st->type->composite)
70 16 : sn = tv_node(sa, st, TV_COMP);
71 : else
72 14 : sn = tv_node(sa, st, TV_BASIC);
73 30 : sn->st = st;
74 :
75 30 : append(n->ctl, sn);
76 :
77 30 : return n;
78 : default:
79 0 : assert(0);
80 : break;
81 : }
82 :
83 : return NULL;
84 : }
85 :
86 : tv_tree *
87 139451 : 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 139451 : 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 43 : mset_value_from_array_constructor(backend *be, tv_tree *t, sql_exp *values, stmt *left, stmt *sel)
146 : {
147 : /* rowid */
148 43 : stmt *rid = stmt_atom_int(be, t->rid_idx);
149 43 : if (!rid)
150 : return false;
151 43 : assert(t->rid);
152 43 : list_append(t->rid, rid);
153 :
154 : /* per value insert actual data, msid(=rowid), msnr(for MSET only) */
155 43 : int msnr_idx = 1; /* NOTE: in mset-value values are 1-offset indexed */
156 43 : list *ms_vals = values->f;
157 124 : for (node *n = ms_vals->h; n; n = n->next, msnr_idx++) {
158 :
159 : /* vals (in the child tree) */
160 81 : assert(list_length(t->ctl) == 1);
161 81 : tv_tree *ct = t->ctl->h->data;
162 81 : tv_parse_values_(be, ct, n->data, left, sel);
163 :
164 : /* msid */
165 81 : stmt *msid = stmt_atom_int(be, t->rid_idx);
166 81 : if (!msid)
167 : return false;
168 81 : list_append(t->msid, msid);
169 :
170 : /* msnr */
171 81 : if (t->tvt == TV_MSET) {
172 81 : stmt *msnr = stmt_atom_int(be, msnr_idx);
173 81 : if (!msnr)
174 : return false;
175 81 : 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 43 : t->rid_idx++;
182 :
183 43 : 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 68 : comp_value_from_parenthesis(backend *be, tv_tree *t, sql_exp *values, stmt *left, stmt *sel)
211 : {
212 68 : assert(values->f);
213 68 : list *ct_vals = values->f;
214 :
215 68 : int cnt = 0;
216 204 : for (node *n = ct_vals->h; n; cnt++, n = n->next)
217 136 : 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 749352 : tv_parse_values_(backend *be, tv_tree *t, sql_exp *value, stmt *left, stmt *sel)
240 : {
241 749352 : stmt *i;
242 749352 : sql_exp* uc;
243 :
244 749352 : switch (t->tvt) {
245 749225 : case TV_BASIC:
246 749225 : i = exp_bin(be, value, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
247 750444 : if (!i)
248 : return false;
249 750444 : assert(t->vals);
250 750444 : list_append(t->vals, i);
251 750444 : break;
252 53 : case TV_MSET:
253 : case TV_SETOF:
254 : //assert(is_convert(value->type));
255 53 : assert(value->f);
256 53 : uc = value;
257 53 : if (is_convert(value->type))
258 50 : uc = value->l;
259 53 : 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 43 : return mset_value_from_array_constructor(be, t, uc, left, sel);
265 74 : break;
266 74 : case TV_COMP:
267 74 : 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 68 : return comp_value_from_parenthesis(be, t, value, left, sel);
273 0 : break;
274 : default:
275 0 : assert(0);
276 : break;
277 : }
278 :
279 750444 : return true;
280 : }
281 :
282 : static inline sql_exp *
283 8 : tv_exp_wrap_list(backend *be, tv_tree *t, list *l)
284 : {
285 16 : sql_exp *e = exp_null(be->mvc->sa, t->st);
286 8 : e->l = e->f = 0;
287 8 : e->f = l;
288 8 : return e;
289 : }
290 :
291 : bool
292 137413 : tv_parse_values(backend *be, tv_tree *t, sql_exp *col_vals, stmt *left, stmt *sel)
293 : {
294 137413 : 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 137597 : bool single_row_val = false;
308 137597 : single_row_val |= col_vals->row;
309 137597 : if ((t->tvt == TV_MSET) || (t->tvt == TV_SETOF)) {
310 : // single value MSET/SETOF of basic type
311 14 : single_row_val |= !((sql_exp*)vals->h->data)->f;
312 : // single value MSET/SETOF of composite type
313 14 : single_row_val |= ((sql_exp*)vals->h->data)->row;
314 : }
315 :
316 137597 : 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 8 : sql_exp *de = tv_exp_wrap_list(be, t, vals);
320 8 : if (false == tv_parse_values_(be, t, de, left, sel))
321 : return false;
322 : } else {
323 887070 : for (node *n = vals->h; n; n = n->next) {
324 749440 : sql_exp *e = n->data;
325 749440 : if (false == tv_parse_values_(be, t, e, left, sel))
326 : return false;
327 : }
328 : }
329 : return true;
330 : }
331 :
332 : stmt *
333 137656 : tv_generate_stmts(backend *be, tv_tree *t)
334 : {
335 137656 : stmt *ap, *tmp, *s;
336 137656 : list *sl;
337 :
338 137656 : switch (t->tvt) {
339 137592 : case TV_BASIC:
340 137592 : return stmt_append_bulk(be, stmt_temp(be, t->st), t->vals);
341 30 : case TV_MSET:
342 : case TV_SETOF:
343 : /* vals (in the child tree) */
344 30 : assert(list_length(t->ctl) == 1);
345 30 : tv_tree *ct = t->ctl->h->data;
346 30 : 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 30 : if (tmp->type == st_list) {
351 : s = tmp;
352 : } else {
353 14 : s = stmt_list(be, sa_list(be->mvc->sa));
354 14 : list_append(s->op4.lval, tmp);
355 : }
356 :
357 : /* msid */
358 30 : tmp = stmt_temp(be, tail_type(t->msid->h->data));
359 30 : ap = stmt_append_bulk(be, tmp, t->msid);
360 30 : append(s->op4.lval, ap);
361 :
362 : /* msnr */
363 30 : if (t->tvt == TV_MSET) {
364 30 : tmp = stmt_temp(be, tail_type(t->msnr->h->data));
365 30 : ap = stmt_append_bulk(be, tmp, t->msnr);
366 30 : append(s->op4.lval, ap);
367 : }
368 :
369 : /* rid */
370 30 : tmp = stmt_temp(be, tail_type(t->rid->h->data));
371 30 : ap = stmt_append_bulk(be, tmp, t->rid);
372 30 : append(s->op4.lval, ap);
373 :
374 : /* we've appended in the stmt_list so update nrcols */
375 30 : stmt_set_nrcols(s);
376 30 : s->subtype = *t->st;
377 30 : return s;
378 34 : case TV_COMP:
379 34 : sl = sa_list(be->mvc->sa);
380 : /* gather all the composite (sub)field's statements */
381 102 : for (node *n = t->ctl->h; n; n = n->next)
382 68 : list_append(sl, tv_generate_stmts(be, n->data));
383 34 : return stmt_list(be, sl);
384 : default:
385 0 : assert(0);
386 : return NULL;
387 : }
388 : return s;
389 : }
|