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 MPL 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_parser.h"
11#include "sql_symbol.h"
12#include "sql_semantic.h"
13#include "sql_env.h"
14#include "sql_privileges.h"
15#include "sql_string.h"
16#include "sql_atom.h"
17
18#include <unistd.h>
19#include <string.h>
20#include <ctype.h>
21
22#include "rel_semantic.h"
23#include "rel_unnest.h"
24#include "rel_optimizer.h"
25
26/*
27 * For debugging purposes we need to be able to convert sql-tokens to
28 * a string representation.
29 *
30 * !SQL ERROR <sqlerrno> : <details>
31 * !SQL DEBUG <details>
32 * !SQL WARNING <details>
33 * !SQL <informative message, reserved for ...rows affected>
34 */
35
36atom *
37sql_add_arg(mvc *sql, atom *v)
38{
39 atom** new_args;
40 int next_size = sql->argmax;
41 if (sql->argc == next_size) {
42 next_size *= 2;
43 new_args = RENEW_ARRAY(atom*,sql->args,next_size);
44 if(new_args) {
45 sql->args = new_args;
46 sql->argmax = next_size;
47 } else
48 return NULL;
49 }
50 sql->args[sql->argc++] = v;
51 return v;
52}
53
54atom *
55sql_set_arg(mvc *sql, int nr, atom *v)
56{
57 atom** new_args;
58 int next_size = sql->argmax;
59 if (nr >= next_size) {
60 next_size *= 2;
61 if (nr >= next_size)
62 next_size = nr*2;
63 new_args = RENEW_ARRAY(atom*,sql->args,next_size);
64 if(new_args) {
65 sql->args = new_args;
66 sql->argmax = next_size;
67 } else
68 return NULL;
69 }
70 if (sql->argc < nr+1)
71 sql->argc = nr+1;
72 sql->args[nr] = v;
73 return v;
74}
75
76void
77sql_add_param(mvc *sql, const char *name, sql_subtype *st)
78{
79 sql_arg *a = SA_ZNEW(sql->sa, sql_arg);
80
81 if (name)
82 a->name = sa_strdup(sql->sa, name);
83 if (st && st->type)
84 a->type = *st;
85 a->inout = ARG_IN;
86 if (name && strcmp(name, "*") == 0)
87 a->type = *sql_bind_localtype("int");
88 if (!sql->params)
89 sql->params = sa_list(sql->sa);
90 list_append(sql->params, a);
91}
92
93sql_arg *
94sql_bind_param(mvc *sql, const char *name)
95{
96 node *n;
97
98 if (sql->params) {
99 for (n = sql->params->h; n; n = n->next) {
100 sql_arg *a = n->data;
101
102 if (a->name && strcmp(a->name, name) == 0)
103 return a;
104 }
105 }
106 return NULL;
107}
108
109static sql_arg *
110sql_bind_paramnr(mvc *sql, int nr)
111{
112 int i=0;
113 node *n;
114
115 if (sql->params && nr < list_length(sql->params)) {
116 for (n = sql->params->h, i=0; n && i<nr; n = n->next, i++)
117 ;
118
119 if (n)
120 return n->data;
121 }
122 return NULL;
123}
124
125atom *
126sql_bind_arg(mvc *sql, int nr)
127{
128 if (nr < sql->argc)
129 return sql->args[nr];
130 return NULL;
131}
132
133void
134sql_destroy_params(mvc *sql)
135{
136 sql->params = NULL;
137}
138
139void
140sql_destroy_args(mvc *sql)
141{
142 sql->argc = 0;
143}
144
145
146sql_schema *
147cur_schema(mvc *sql)
148{
149 return sql->session->schema;
150}
151
152sql_schema *
153tmp_schema(mvc *sql)
154{
155 return mvc_bind_schema(sql, "tmp");
156}
157
158char *
159qname_schema(dlist *qname)
160{
161 assert(qname && qname->h);
162
163 if (dlist_length(qname) == 2) {
164 return qname->h->data.sval;
165 } else if (dlist_length(qname) == 3) {
166 return qname->h->next->data.sval;
167 }
168 return NULL;
169}
170
171char *
172qname_table(dlist *qname)
173{
174 assert(qname && qname->h);
175
176 if (dlist_length(qname) == 1) {
177 return qname->h->data.sval;
178 } else if (dlist_length(qname) == 2) {
179 return qname->h->next->data.sval;
180 } else if (dlist_length(qname) == 3) {
181 return qname->h->next->next->data.sval;
182 }
183 return "unknown";
184}
185
186char *
187qname_catalog(dlist *qname)
188{
189 assert(qname && qname->h);
190
191 if (dlist_length(qname) == 3) {
192 return qname->h->data.sval;
193 }
194
195 return NULL;
196}
197
198
199int
200set_type_param(mvc *sql, sql_subtype *type, int nr)
201{
202 sql_arg *a = sql_bind_paramnr(sql, nr);
203
204 if (!a)
205 return -1;
206 a->type = *type;
207 return 0;
208}
209
210sql_subtype *
211supertype(sql_subtype *super, sql_subtype *r, sql_subtype *i)
212{
213 /* first find super type */
214 char *tpe = r->type->sqlname;
215 int radix = r->type->radix;
216 int digits = 0;
217 int idigits = i->digits;
218 int rdigits = r->digits;
219 unsigned int scale = sql_max(i->scale, r->scale);
220 sql_subtype lsuper;
221
222 lsuper = *r;
223 if (i->type->base.id > r->type->base.id ||
224 (EC_VARCHAR(i->type->eclass) && !EC_VARCHAR(r->type->eclass))) {
225 lsuper = *i;
226 radix = i->type->radix;
227 tpe = i->type->sqlname;
228 }
229 if (!lsuper.type->localtype)
230 tpe = "smallint";
231 /*
232 * In case of different radix we should change one.
233 */
234 if (i->type->radix != r->type->radix) {
235 if (radix == 10 || radix == 0 /* strings */) {
236 /* change to radix 10 */
237 if (i->type->radix == 2)
238 idigits = bits2digits(idigits);
239 if (r->type->radix == 2)
240 rdigits = bits2digits(rdigits);
241 } else if (radix == 2) { /* change to radix 2 */
242 if (i->type->radix == 10)
243 idigits = digits2bits(idigits);
244 if (r->type->radix == 10)
245 rdigits = digits2bits(rdigits);
246 }
247 }
248 /* handle OID horror */
249 if (i->type->radix == r->type->radix && i->type->base.id < r->type->base.id && strcmp(i->type->sqlname, "oid") == 0)
250 tpe = i->type->sqlname;
251 if (scale == 0 && (idigits == 0 || rdigits == 0)) {
252 sql_find_subtype(&lsuper, tpe, 0, 0);
253 } else {
254 digits = sql_max(idigits - i->scale, rdigits - r->scale);
255 sql_find_subtype(&lsuper, tpe, digits+scale, scale);
256 }
257 *super = lsuper;
258 return super;
259}
260
261char * toUpperCopy(char *dest, const char *src)
262{
263 size_t i, len;
264
265 if (src == NULL) {
266 *dest = '\0';
267 return(dest);
268 }
269
270 len = _strlen(src);
271 for (i = 0; i < len; i++)
272 dest[i] = (char)toupper((int)src[i]);
273
274 dest[i] = '\0';
275 return(dest);
276}
277
278char *dlist2string(mvc *sql, dlist *l, int expression, char **err)
279{
280 char *b = NULL;
281 dnode *n;
282
283 for (n=l->h; n; n = n->next) {
284 char *s = NULL;
285
286 if (n->type == type_string && n->data.sval)
287 s = _STRDUP(n->data.sval);
288 else if (n->type == type_symbol)
289 s = symbol2string(sql, n->data.sym, expression, err);
290
291 if (!s) {
292 _DELETE(b);
293 return NULL;
294 }
295 if (b) {
296 char *o = NEW_ARRAY(char, strlen(b) + strlen(s) + 2);
297 if (o)
298 stpcpy(stpcpy(stpcpy(o, b), "."), s);
299 _DELETE(b);
300 _DELETE(s);
301 b = o;
302 if (b == NULL)
303 return NULL;
304 } else {
305 b = s;
306 }
307 }
308 return b;
309}
310
311char *symbol2string(mvc *sql, symbol *se, int expression, char **err) /**/
312{
313 int len = 0;
314 char buf[BUFSIZ];
315
316 buf[0] = 0;
317 switch (se->token) {
318 case SQL_NOP: {
319 dnode *lst = se->data.lval->h;
320 dnode *ops = lst->next->data.lval->h;
321 char *op = qname_fname(lst->data.lval);
322
323 len = snprintf( buf+len, BUFSIZ-len, "%s(", op);
324 for (; ops; ops = ops->next) {
325 char *tmp = symbol2string(sql, ops->data.sym, expression, err);
326 if (tmp == NULL)
327 return NULL;
328 len = snprintf( buf+len, BUFSIZ-len, "%s%s",
329 tmp,
330 (ops->next)?",":"");
331 _DELETE(tmp);
332 }
333 len = snprintf( buf+len, BUFSIZ-len, ")");
334 } break;
335 case SQL_BINOP: {
336 dnode *lst = se->data.lval->h;
337 char *op = qname_fname(lst->data.lval);
338 char *l;
339 char *r;
340 l = symbol2string(sql, lst->next->data.sym, expression, err);
341 if (l == NULL)
342 return NULL;
343 r = symbol2string(sql, lst->next->next->data.sym, expression, err);
344 if (r == NULL) {
345 _DELETE(l);
346 return NULL;
347 }
348 len = snprintf( buf+len, BUFSIZ-len, "%s(%s,%s)", op, l, r);
349 _DELETE(l);
350 _DELETE(r);
351 } break;
352 case SQL_OP: {
353 dnode *lst = se->data.lval->h;
354 char *op = qname_fname(lst->data.lval);
355 len = snprintf( buf+len, BUFSIZ-len, "%s()", op );
356 } break;
357 case SQL_UNOP: {
358 dnode *lst = se->data.lval->h;
359 char *op = qname_fname(lst->data.lval);
360 char *l = symbol2string(sql, lst->next->data.sym, expression, err);
361 if (l == NULL)
362 return NULL;
363 len = snprintf( buf+len, BUFSIZ-len, "%s(%s)", op, l);
364 _DELETE(l);
365 break;
366 }
367 case SQL_PARAMETER:
368 strcpy(buf,"?");
369 break;
370 case SQL_NULL:
371 strcpy(buf,"NULL");
372 break;
373 case SQL_ATOM:{
374 AtomNode *an = (AtomNode *) se;
375 if (an && an->a)
376 return atom2sql(an->a);
377 else
378 strcpy(buf,"NULL");
379 break;
380 }
381 case SQL_NEXT:{
382 const char *seq = qname_table(se->data.lval);
383 const char *sname = qname_schema(se->data.lval);
384 const char *s;
385
386 if (!sname)
387 sname = sql->session->schema->base.name;
388 s = sql_escape_ident(seq);
389 if(!s)
390 return NULL;
391 len = snprintf( buf+len, BUFSIZ-len, "next value for \"%s\".\"%s\"", sname, s);
392 c_delete(s);
393 } break;
394 case SQL_IDENT:
395 case SQL_COLUMN: {
396 /* can only be variables */
397 dlist *l = se->data.lval;
398 assert(l->h->type != type_lng);
399 if (dlist_length(l) == 1 && l->h->type == type_int) {
400 atom *a = sql_bind_arg(sql, l->h->data.i_val);
401 return atom2sql(a);
402 } else if (expression && dlist_length(l) == 1 && l->h->type == type_string) {
403 /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */
404 return _STRDUP(l->h->data.sval);
405 } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) {
406 char *first = l->h->data.sval;
407 char *second = l->h->next->data.sval;
408 char *res;
409
410 if(!first || !second) {
411 return NULL;
412 }
413 res = NEW_ARRAY(char, strlen(first) + strlen(second) + 2);
414 if (res) {
415 stpcpy(stpcpy(stpcpy(res, first), "."), second);
416 }
417 return res;
418 } else {
419 char *e = dlist2string(sql, l, expression, err);
420 if (e)
421 *err = e;
422 }
423 return NULL;
424 }
425 case SQL_CAST: {
426 dlist *dl = se->data.lval;
427 char *val;
428 char *tpe;
429
430 val = symbol2string(sql, dl->h->data.sym, expression, err);
431 if (val == NULL)
432 return NULL;
433 tpe = subtype2string(&dl->h->next->data.typeval);
434 if (tpe == NULL) {
435 _DELETE(val);
436 return NULL;
437 }
438 len = snprintf( buf+len, BUFSIZ-len, "cast ( %s as %s )",
439 val, tpe);
440 _DELETE(val);
441 _DELETE(tpe);
442 break;
443 }
444 case SQL_AGGR:
445 case SQL_SELECT:
446 case SQL_CASE:
447 case SQL_COALESCE:
448 case SQL_NULLIF:
449 default:
450 return NULL;
451 }
452 return _STRDUP(buf);
453}
454