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/*
10 * authors M Kersten, N Nes
11 * SQL catalog support implementation
12 * This module contains the wrappers around the SQL catalog operations
13 */
14#include "monetdb_config.h"
15#include "sql_cat.h"
16#include "sql_gencode.h"
17#include "sql_optimizer.h"
18#include "sql_scenario.h"
19#include "sql_mvc.h"
20#include "sql_qc.h"
21#include "sql_partition.h"
22#include "sql_statistics.h"
23#include "mal_namespace.h"
24#include "opt_prelude.h"
25#include "querylog.h"
26#include "mal_builder.h"
27#include "mal_debugger.h"
28
29#include "rel_select.h"
30#include "rel_unnest.h"
31#include "rel_optimizer.h"
32#include "rel_prop.h"
33#include "rel_rel.h"
34#include "rel_exp.h"
35#include "rel_bin.h"
36#include "rel_dump.h"
37#include "rel_remote.h"
38#include "orderidx.h"
39
40#define initcontext() \
41 if ((msg = getSQLContext(cntxt, mb, &sql, NULL)) != NULL)\
42 return msg;\
43 if ((msg = checkSQLContext(cntxt)) != NULL)\
44 return msg;\
45 if (STORE_READONLY)\
46 throw(SQL,"sql.cat",SQLSTATE(25006) "Schema statements cannot be executed on a readonly database.");
47
48static char *
49SaveArgReference(MalStkPtr stk, InstrPtr pci, int arg)
50{
51 char *val = *getArgReference_str(stk, pci, arg);
52
53 if (val && strcmp(val, str_nil) == 0)
54 val = NULL;
55 return val;
56}
57
58static int
59table_has_updates(sql_trans *tr, sql_table *t)
60{
61 node *n;
62 int cnt = 0;
63
64 for ( n = t->columns.set->h; !cnt && n; n = n->next) {
65 sql_column *c = n->data;
66 BAT *b = store_funcs.bind_col(tr, c, RD_UPD_ID);
67 if ( b == 0)
68 return -1;
69 cnt |= BATcount(b) > 0;
70 if (isTable(t) && t->access != TABLE_READONLY && (!isNew(t) /* alter */ ) &&
71 t->persistence == SQL_PERSIST && !t->commit_action)
72 cnt |= store_funcs.count_col(tr, c, 0) > 0;
73 BBPunfix(b->batCacheid);
74 }
75 return cnt;
76}
77
78static char *
79rel_check_tables(sql_table *nt, sql_table *nnt, const char *errtable)
80{
81 node *n, *m, *nn, *mm;
82
83 if (cs_size(&nt->columns) != cs_size(&nnt->columns))
84 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table doesn't match %s definition", errtable, errtable);
85 for (n = nt->columns.set->h, m = nnt->columns.set->h; n && m; n = n->next, m = m->next) {
86 sql_column *nc = n->data;
87 sql_column *mc = m->data;
88
89 if (subtype_cmp(&nc->type, &mc->type) != 0)
90 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table column type doesn't match %s definition", errtable, errtable);
91 if(isRangePartitionTable(nt) || isListPartitionTable(nt)) {
92 if (nc->null != mc->null)
93 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table column NULL check doesn't match %s definition", errtable, errtable);
94 if ((!nc->def && mc->def) || (nc->def && !mc->def) || (nc->def && mc->def && strcmp(nc->def, mc->def) != 0))
95 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table column DEFAULT value doesn't match %s definition", errtable, errtable);
96 }
97 }
98 if(isNonPartitionedTable(nt)) {
99 if (cs_size(&nt->idxs) != cs_size(&nnt->idxs))
100 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table index doesn't match %s definition", errtable, errtable);
101 if (cs_size(&nt->idxs))
102 for (n = nt->idxs.set->h, m = nnt->idxs.set->h; n && m; n = n->next, m = m->next) {
103 sql_idx *ni = n->data;
104 sql_idx *mi = m->data;
105
106 if (ni->type != mi->type)
107 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table index type doesn't match %s definition", errtable, errtable);
108 }
109 } else { //for partitioned tables we allow indexes but the key set must be exactly the same
110 if (cs_size(&nt->keys) != cs_size(&nnt->keys))
111 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table key doesn't match %s definition", errtable, errtable);
112 if (cs_size(&nt->keys))
113 for (n = nt->keys.set->h, m = nnt->keys.set->h; n && m; n = n->next, m = m->next) {
114 sql_key *ni = n->data;
115 sql_key *mi = m->data;
116
117 if (ni->type != mi->type)
118 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table key type doesn't match %s definition", errtable, errtable);
119 if (list_length(ni->columns) != list_length(mi->columns))
120 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table key type doesn't match %s definition", errtable, errtable);
121 for (nn = ni->columns->h, mm = mi->columns->h; nn && mm; nn = nn->next, mm = mm->next) {
122 sql_kc *nni = nn->data;
123 sql_kc *mmi = mm->data;
124
125 if (nni->c->colnr != mmi->c->colnr)
126 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table key's columns doesn't match %s definition", errtable, errtable);
127 }
128 }
129 }
130
131 for(sql_table *up = nt->p ; up ; up = up->p) {
132 if(!strcmp(up->s->base.name, nnt->s->base.name) && !strcmp(up->base.name, nnt->base.name))
133 throw(SQL,"sql.rel_check_tables",SQLSTATE(3F000) "ALTER %s: to be added table is a parent of the %s", errtable, errtable);
134 }
135 return MAL_SUCCEED;
136}
137
138static char*
139validate_alter_table_add_table(mvc *sql, char* call, char *msname, char *mtname, char *psname, char *ptname,
140 sql_table **mt, sql_table **pt, int update)
141{
142 sql_schema *ms = mvc_bind_schema(sql, msname), *ps = mvc_bind_schema(sql, psname);
143 sql_table *rmt = NULL, *rpt = NULL;
144
145 if (ms)
146 rmt = mvc_bind_table(sql, ms, mtname);
147 if (ps)
148 rpt = mvc_bind_table(sql, ps, ptname);
149 *mt = rmt;
150 *pt = rpt;
151 if (!update && rmt && (!isMergeTable(rmt) && !isReplicaTable(rmt)))
152 throw(SQL,call,SQLSTATE(42S02) "ALTER TABLE: cannot add table '%s.%s' to table '%s.%s'", psname, ptname, msname, mtname);
153 if (rmt && rpt) {
154 char *msg;
155 node *n = cs_find_id(&rmt->members, rpt->base.id);
156 const char *errtable = TABLE_TYPE_DESCRIPTION(rmt->type, rmt->properties);
157
158 if (isView(rpt))
159 throw(SQL,call,SQLSTATE(42000) "ALTER TABLE: can't add a view into a %s", errtable);
160 if (ms->base.id != ps->base.id)
161 throw(SQL,call,SQLSTATE(42000) "ALTER TABLE: all children tables of '%s.%s' must be part of schema '%s'", msname, mtname, msname);
162 if (n && !update)
163 throw(SQL,call,SQLSTATE(42S02) "ALTER TABLE: table '%s.%s' is already part of the %s '%s.%s'", psname, ptname, errtable, msname, mtname);
164 if (!n && update)
165 throw(SQL,call,SQLSTATE(42S02) "ALTER TABLE: table '%s.%s' isn't part of the %s '%s.%s'", psname, ptname, errtable, msname, mtname);
166 if ((msg = rel_check_tables(rmt, rpt, errtable)) != NULL)
167 return msg;
168 return MAL_SUCCEED;
169 } else if (rmt) {
170 throw(SQL,call,SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", ptname, psname);
171 } else {
172 throw(SQL,call,SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", mtname, msname);
173 }
174}
175
176static char *
177alter_table_add_table(mvc *sql, char *msname, char *mtname, char *psname, char *ptname)
178{
179 sql_table *mt = NULL, *pt = NULL;
180 str msg = validate_alter_table_add_table(sql, "sql.alter_table_add_table", msname, mtname, psname, ptname, &mt, &pt, 0);
181
182 if(msg == MAL_SUCCEED)
183 sql_trans_add_table(sql->session->tr, mt, pt);
184
185 return msg;
186}
187
188static char *
189alter_table_add_range_partition(mvc *sql, char *msname, char *mtname, char *psname, char *ptname, ptr min, ptr max,
190 int with_nills, int update)
191{
192 sql_table *mt = NULL, *pt = NULL;
193 sql_part *err = NULL;
194 str msg = MAL_SUCCEED, err_min = NULL, err_max = NULL, conflict_err_min = NULL, conflict_err_max = NULL;
195 int tp1 = 0, errcode = 0, min_null = 0, max_null = 0;
196 size_t length = 0;
197 ssize_t (*atomtostr)(str *, size_t *, const void *, bool);
198 sql_subtype tpe;
199
200 if((msg = validate_alter_table_add_table(sql, "sql.alter_table_add_range_partition", msname, mtname, psname, ptname,
201 &mt, &pt, update))) {
202 return msg;
203 } else if(!isRangePartitionTable(mt)) {
204 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000)
205 "ALTER TABLE: cannot add range partition into a %s table",
206 (mt->type == tt_merge_table)?"merge":"list partition");
207 goto finish;
208 } else if(!update && pt->p) {
209 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000)
210 "ALTER TABLE: table %s.%s is already part of another range partition table",
211 psname, ptname);
212 goto finish;
213 }
214
215 find_partition_type(&tpe, mt);
216 tp1 = tpe.type->localtype;
217 min_null = ATOMcmp(tp1, min, ATOMnilptr(tp1)) == 0;
218 max_null = ATOMcmp(tp1, max, ATOMnilptr(tp1)) == 0;
219
220 if(max_null && min_null && !with_nills) {
221 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) "ALTER TABLE: range bound cannot be null");
222 goto finish;
223 } else if(!min_null && !max_null && ATOMcmp(tp1, min, max) > 0) {
224 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) "ALTER TABLE: minimum value is higher than maximum value");
225 goto finish;
226 }
227
228 errcode = sql_trans_add_range_partition(sql->session->tr, mt, pt, tpe, min, max, with_nills, update, &err);
229 switch(errcode) {
230 case 0:
231 break;
232 case -1:
233 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL);
234 break;
235 case -2:
236 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000)
237 "ALTER TABLE: minimum value length is higher than %d", STORAGE_MAX_VALUE_LENGTH);
238 break;
239 case -3:
240 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000)
241 "ALTER TABLE: maximum value length is higher than %d", STORAGE_MAX_VALUE_LENGTH);
242 break;
243 case -4:
244 assert(err);
245 if(with_nills && err->with_nills) {
246 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000)
247 "ALTER TABLE: conflicting partitions: table %s.%s stores null values and only "
248 "one partition can store null values at the time", err->t->s->base.name, err->t->base.name);
249 } else {
250 atomtostr = BATatoms[tp1].atomToStr;
251 if(atomtostr(&conflict_err_min, &length, err->part.range.minvalue, true) < 0) {
252 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL);
253 } else if(atomtostr(&conflict_err_max, &length, err->part.range.maxvalue, true) < 0) {
254 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL);
255 } else if(atomtostr(&err_min, &length, min, true) < 0) {
256 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL);
257 } else if(atomtostr(&err_max, &length, max, true) < 0) {
258 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL);
259 } else {
260 sql_table *errt = mvc_bind_table(sql, mt->s, err->base.name);
261 msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000)
262 "ALTER TABLE: conflicting partitions: %s to %s and %s to %s from table %s.%s",
263 err_min, err_max, conflict_err_min, conflict_err_max, errt->s->base.name, errt->base.name);
264 }
265 }
266 break;
267 default:
268 assert(0);
269 }
270
271finish:
272 if(err_min)
273 GDKfree(err_min);
274 if(err_max)
275 GDKfree(err_max);
276 if(conflict_err_min)
277 GDKfree(conflict_err_min);
278 if(conflict_err_max)
279 GDKfree(conflict_err_max);
280 if(msg != MAL_SUCCEED)
281 pt->p = NULL;
282 return msg;
283}
284
285static char *
286alter_table_add_value_partition(mvc *sql, MalStkPtr stk, InstrPtr pci, char *msname, char *mtname, char *psname,
287 char *ptname, int with_nills, int update)
288{
289 sql_table *mt = NULL, *pt = NULL;
290 str msg = MAL_SUCCEED;
291 sql_part *err = NULL;
292 int errcode = 0, i = 0, ninserts = 0;
293 list *values = list_new(sql->session->tr->sa, (fdestroy) NULL);
294 sql_subtype tpe;
295
296 if((msg = validate_alter_table_add_table(sql, "sql.alter_table_add_value_partition", msname, mtname, psname, ptname,
297 &mt, &pt, update))) {
298 return msg;
299 } else if(!isListPartitionTable(mt)) {
300 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000)
301 "ALTER TABLE: cannot add value partition into a %s table",
302 (mt->type == tt_merge_table)?"merge":"range partition");
303 goto finish;
304 } else if(!update && pt->p) {
305 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000)
306 "ALTER TABLE: table %s.%s is already part of another list partition table",
307 psname, ptname);
308 goto finish;
309 }
310
311 find_partition_type(&tpe, mt);
312 ninserts = pci->argc - pci->retc - 6;
313 if(ninserts <= 0 && !with_nills) {
314 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000) "ALTER TABLE: no values in the list");
315 goto finish;
316 }
317 for( i = pci->retc+6; i < pci->argc; i++){
318 sql_part_value *nextv = NULL;
319 ValRecord *vnext = &(stk)->stk[(pci)->argv[i]];
320 ptr pnext = VALget(vnext);
321 size_t len = ATOMlen(vnext->vtype, pnext);
322
323 if(VALisnil(vnext)) { /* check for an eventual null value which cannot be */
324 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000)
325 "ALTER TABLE: list value cannot be null");
326 goto finish;
327 }
328
329 nextv = SA_ZNEW(sql->session->tr->sa, sql_part_value); /* instantiate the part value */
330 nextv->tpe = tpe;
331 nextv->value = sa_alloc(sql->session->tr->sa, len);
332 memcpy(nextv->value, pnext, len);
333 nextv->length = len;
334
335 if(list_append_sorted(values, nextv, sql_values_list_element_validate_and_insert) != NULL) {
336 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000)
337 "ALTER TABLE: there are duplicated values in the list");
338 goto finish;
339 }
340 }
341
342 errcode = sql_trans_add_value_partition(sql->session->tr, mt, pt, tpe, values, with_nills, update, &err);
343 switch(errcode) {
344 case 0:
345 break;
346 case -1:
347 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000)
348 "ALTER TABLE: the new partition is conflicting with the existing partition %s.%s",
349 err->t->s->base.name, err->t->base.name);
350 break;
351 default:
352 msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000)
353 "ALTER TABLE: value at position %d length is higher than %d",
354 (errcode * -1) - 1, STORAGE_MAX_VALUE_LENGTH);
355 break;
356 }
357
358finish:
359 if(msg != MAL_SUCCEED)
360 pt->p = NULL;
361 return msg;
362}
363
364static char *
365alter_table_del_table(mvc *sql, char *msname, char *mtname, char *psname, char *ptname, int drop_action)
366{
367 sql_schema *ms = mvc_bind_schema(sql, msname), *ps = mvc_bind_schema(sql, psname);
368 sql_table *mt = NULL, *pt = NULL;
369
370 if (ms)
371 mt = mvc_bind_table(sql, ms, mtname);
372 if (ps)
373 pt = mvc_bind_table(sql, ps, ptname);
374 if (mt && pt) {
375 node *n = NULL;
376
377 if (!pt || (n = cs_find_id(&mt->members, pt->base.id)) == NULL)
378 throw(SQL,"sql.alter_table_del_table",SQLSTATE(42S02) "ALTER TABLE: table '%s.%s' isn't part of the MERGE TABLE '%s.%s'", psname, ptname, msname, mtname);
379
380 sql_trans_del_table(sql->session->tr, mt, pt, drop_action);
381 } else if (mt) {
382 throw(SQL,"sql.alter_table_del_table",SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", ptname, psname);
383 } else {
384 throw(SQL,"sql.alter_table_del_table",SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", mtname, msname);
385 }
386 return MAL_SUCCEED;
387}
388
389static char *
390alter_table_set_access(mvc *sql, char *sname, char *tname, int access)
391{
392 sql_schema *s = mvc_bind_schema(sql, sname);
393 sql_table *t = NULL;
394
395 if (s)
396 t = mvc_bind_table(sql, s, tname);
397 if (t) {
398 if (isMergeTable(t))
399 throw(SQL,"sql.alter_table_set_access",SQLSTATE(42S02) "ALTER TABLE: read only MERGE TABLES are not supported");
400 if (t->access != access) {
401 if (access && table_has_updates(sql->session->tr, t))
402 throw(SQL,"sql.alter_table_set_access",SQLSTATE(40000) "ALTER TABLE: set READ or INSERT ONLY not possible with outstanding updates (wait until updates are flushed)\n");
403
404 mvc_access(sql, t, access);
405 if (access == 0)
406 sql_drop_statistics(sql, t);
407 }
408 } else {
409 throw(SQL,"sql.alter_table_set_access",SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", tname, sname);
410 }
411 return MAL_SUCCEED;
412}
413
414static char *
415create_trigger(mvc *sql, char *sname, char *tname, char *triggername, int time, int orientation, int event, char *old_name, char *new_name, char *condition, char *query)
416{
417 sql_trigger *tri = NULL;
418 sql_schema *s = NULL;
419 sql_table *t;
420
421 if (sname && !(s = mvc_bind_schema(sql, sname)))
422 throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER: no such schema '%s'", sname);
423 if (!s)
424 s = cur_schema(sql);
425 if (!mvc_schema_privs(sql, s))
426 throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
427 if (mvc_bind_trigger(sql, s, triggername) != NULL)
428 throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER: name '%s' already in use", triggername);
429
430 if (!(t = mvc_bind_table(sql, s, tname)))
431 throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER: unknown table '%s'", tname);
432
433 if (isView(t))
434 throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER: cannot create trigger on view '%s'", tname);
435
436 tri = mvc_create_trigger(sql, t, triggername, time, orientation, event, old_name, new_name, condition, query);
437 if (tri) {
438 char *buf;
439 sql_rel *r = NULL;
440 sql_allocator *sa = sql->sa;
441
442 sql->sa = sa_create();
443 if(!sql->sa)
444 throw(SQL, "sql.catalog",SQLSTATE(HY001) MAL_MALLOC_FAIL);
445 buf = sa_strdup(sql->sa, query);
446 if(!buf)
447 throw(SQL, "sql.catalog",SQLSTATE(HY001) MAL_MALLOC_FAIL);
448 r = rel_parse(sql, s, buf, m_deps);
449 if (r)
450 r = rel_unnest(sql, r);
451 if (r)
452 r = rel_optimizer(sql, r, 0);
453 if (r) {
454 list *id_l = rel_dependencies(sql, r);
455
456 mvc_create_dependencies(sql, id_l, tri->base.id, TRIGGER_DEPENDENCY);
457 }
458 sa_destroy(sql->sa);
459 sql->sa = sa;
460 }
461 return MAL_SUCCEED;
462}
463
464static char *
465drop_trigger(mvc *sql, char *sname, char *tname, int if_exists)
466{
467 sql_trigger *tri = NULL;
468 sql_schema *s = NULL;
469
470 if (sname && !(s = mvc_bind_schema(sql, sname)))
471 throw(SQL,"sql.drop_trigger",SQLSTATE(3F000) "DROP TRIGGER: no such schema '%s'", sname);
472 if (!s)
473 s = cur_schema(sql);
474 assert(s);
475 if (!mvc_schema_privs(sql, s))
476 throw(SQL,"sql.drop_trigger",SQLSTATE(3F000) "DROP TRIGGER: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
477
478 if ((tri = mvc_bind_trigger(sql, s, tname)) == NULL) {
479 if(if_exists)
480 return MAL_SUCCEED;
481 throw(SQL,"sql.drop_trigger", SQLSTATE(3F000) "DROP TRIGGER: unknown trigger %s\n", tname);
482 }
483 if(mvc_drop_trigger(sql, s, tri))
484 throw(SQL,"sql.drop_trigger", SQLSTATE(HY001) MAL_MALLOC_FAIL);
485 return MAL_SUCCEED;
486}
487
488static char *
489drop_table(mvc *sql, char *sname, char *tname, int drop_action, int if_exists)
490{
491 sql_schema *s = NULL;
492 sql_table *t = NULL;
493 node *n;
494
495 if (sname && !(s = mvc_bind_schema(sql, sname)))
496 throw(SQL,"sql.drop_table",SQLSTATE(3F000) "DROP TABLE: no such schema '%s'", sname);
497 if (!s)
498 s = cur_schema(sql);
499 t = mvc_bind_table(sql, s, tname);
500 if (!t && !sname) {
501 s = tmp_schema(sql);
502 t = mvc_bind_table(sql, s, tname);
503 }
504 if (!t) {
505 if (if_exists)
506 return MAL_SUCCEED;
507 throw(SQL,"sql.droptable", SQLSTATE(42S02) "DROP TABLE: no such table '%s'", tname);
508 } else if (isView(t)) {
509 throw(SQL,"sql.droptable", SQLSTATE(42000) "DROP TABLE: cannot drop VIEW '%s'", tname);
510 } else if (t->system) {
511 throw(SQL,"sql.droptable", SQLSTATE(42000) "DROP TABLE: cannot drop system table '%s'", tname);
512 } else if (!mvc_schema_privs(sql, s) && !(isTempSchema(s) && t->persistence == SQL_LOCAL_TEMP)) {
513 throw(SQL,"sql.droptable",SQLSTATE(42000) "DROP TABLE: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
514 }
515 if (!drop_action && t->keys.set) {
516 for (n = t->keys.set->h; n; n = n->next) {
517 sql_key *k = n->data;
518
519 if (k->type == ukey || k->type == pkey) {
520 sql_ukey *uk = (sql_ukey *) k;
521
522 if (uk->keys && list_length(uk->keys)) {
523 node *l = uk->keys->h;
524
525 for (; l; l = l->next) {
526 k = l->data;
527 /* make sure it is not a self referencing key */
528 if (k->t != t)
529 throw(SQL,"sql.droptable", SQLSTATE(40000) "DROP TABLE: FOREIGN KEY %s.%s depends on %s", k->t->base.name, k->base.name, tname);
530 }
531 }
532 }
533 }
534 }
535
536 if (!drop_action && mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY, NULL))
537 throw (SQL,"sql.droptable",SQLSTATE(42000) "DROP TABLE: unable to drop table %s (there are database objects which depend on it)\n", t->base.name);
538
539 return mvc_drop_table(sql, s, t, drop_action);
540}
541
542static char *
543drop_view(mvc *sql, char *sname, char *tname, int drop_action, int if_exists)
544{
545 sql_table *t = NULL;
546 sql_schema *ss = NULL;
547
548 if (sname != NULL && (ss = mvc_bind_schema(sql, sname)) == NULL)
549 throw(SQL,"sql.dropview", SQLSTATE(3F000) "DROP VIEW: no such schema '%s'", sname);
550
551 if (ss == NULL)
552 ss = cur_schema(sql);
553
554 t = mvc_bind_table(sql, ss, tname);
555 if (!mvc_schema_privs(sql, ss) && !(isTempSchema(ss) && t && t->persistence == SQL_LOCAL_TEMP)) {
556 throw(SQL,"sql.dropview", SQLSTATE(42000) "DROP VIEW: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), ss->base.name);
557 } else if (!t) {
558 if(if_exists){
559 return MAL_SUCCEED;
560 }
561 throw(SQL,"sql.drop_view",SQLSTATE(42S02) "DROP VIEW: unknown view '%s'", tname);
562 } else if (!isView(t)) {
563 throw(SQL,"sql.drop_view", SQLSTATE(42000) "DROP VIEW: unable to drop view '%s': is a table", tname);
564 } else if (t->system) {
565 throw(SQL,"sql.drop_view", SQLSTATE(42000) "DROP VIEW: cannot drop system view '%s'", tname);
566 } else if (!drop_action && mvc_check_dependency(sql, t->base.id, VIEW_DEPENDENCY, NULL)) {
567 throw(SQL,"sql.drop_view", SQLSTATE(42000) "DROP VIEW: cannot drop view '%s', there are database objects which depend on it", t->base.name);
568 }
569 return mvc_drop_table(sql, ss, t, drop_action);
570}
571
572static str
573drop_key(mvc *sql, char *sname, char *kname, int drop_action)
574{
575 sql_key *key;
576 sql_schema *ss = NULL;
577
578 if (sname != NULL && (ss = mvc_bind_schema(sql, sname)) == NULL)
579 throw(SQL,"drop_key", SQLSTATE(3F000) "ALTER TABLE: no such schema '%s'", sname);
580
581 if (ss == NULL)
582 ss = cur_schema(sql);
583
584 if ((key = mvc_bind_key(sql, ss, kname)) == NULL)
585 throw(SQL,"sql.drop_key", SQLSTATE(42000) "ALTER TABLE: no such constraint '%s'", kname);
586 if (!drop_action && mvc_check_dependency(sql, key->base.id, KEY_DEPENDENCY, NULL))
587 throw(SQL,"sql.drop_key", SQLSTATE(42000) "ALTER TABLE: cannot drop constraint '%s': there are database objects which depend on it", key->base.name);
588 if(mvc_drop_key(sql, ss, key, drop_action))
589 throw(SQL,"sql.drop_key", SQLSTATE(HY001) MAL_MALLOC_FAIL);
590 return MAL_SUCCEED;
591}
592
593static str
594drop_index(Client cntxt, mvc *sql, char *sname, char *iname)
595{
596 sql_schema *s = NULL;
597 sql_idx *i = NULL;
598
599 if (!(s = mvc_bind_schema(sql, sname)))
600 throw(SQL,"sql.drop_index", SQLSTATE(3F000) "DROP INDEX: no such schema '%s'", sname);
601 i = mvc_bind_idx(sql, s, iname);
602 if (!i) {
603 throw(SQL,"sql.drop_index", SQLSTATE(42S12) "DROP INDEX: no such index '%s'", iname);
604 } else if (!mvc_schema_privs(sql, s)) {
605 throw(SQL,"sql.drop_index", SQLSTATE(42000) "DROP INDEX: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
606 } else {
607 if (i->type == ordered_idx) {
608 sql_kc *ic = i->columns->h->data;
609 BAT *b = mvc_bind(sql, s->base.name, ic->c->t->base.name, ic->c->base.name, 0);
610 if(b) {
611 OIDXdropImplementation(cntxt, b);
612 BBPunfix(b->batCacheid);
613 }
614 }
615 if (i->type == imprints_idx) {
616 sql_kc *ic = i->columns->h->data;
617 BAT *b = mvc_bind(sql, s->base.name, ic->c->t->base.name, ic->c->base.name, 0);
618 if(b) {
619 IMPSdestroy(b);
620 BBPunfix(b->batCacheid);
621 }
622 }
623 if(mvc_drop_idx(sql, s, i))
624 throw(SQL,"sql.drop_index", SQLSTATE(HY001) MAL_MALLOC_FAIL);
625 }
626 return NULL;
627}
628
629static str
630create_seq(mvc *sql, char *sname, char *seqname, sql_sequence *seq)
631{
632 sql_schema *s = NULL;
633
634 (void)seqname;
635 if (sname && !(s = mvc_bind_schema(sql, sname)))
636 throw(SQL,"sql.create_seq", SQLSTATE(3F000) "CREATE SEQUENCE: no such schema '%s'", sname);
637 if (s == NULL)
638 s = cur_schema(sql);
639 if (find_sql_sequence(s, seq->base.name)) {
640 throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: name '%s' already in use", seq->base.name);
641 } else if (!mvc_schema_privs(sql, s)) {
642 throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: insufficient privileges for '%s' in schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
643 } else if (is_lng_nil(seq->start) || is_lng_nil(seq->minvalue) || is_lng_nil(seq->maxvalue) ||
644 is_lng_nil(seq->increment) || is_lng_nil(seq->cacheinc) || is_bit_nil(seq->cycle)) {
645 throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: sequence properties must be non-NULL");
646 }
647 if (seq->minvalue && seq->start < seq->minvalue)
648 throw(SQL, "sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: start value is lesser than the minimum ("LLFMT" < "LLFMT")", seq->start, seq->minvalue);
649 if (seq->maxvalue && seq->start > seq->maxvalue)
650 throw(SQL, "sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: start value is higher than the maximum ("LLFMT" > "LLFMT")", seq->start, seq->maxvalue);
651 if (seq->minvalue && seq->maxvalue && seq->maxvalue < seq->minvalue)
652 throw(SQL, "sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: maximum value is lesser than the minimum ("LLFMT" < "LLFMT")", seq->maxvalue, seq->minvalue);
653 sql_trans_create_sequence(sql->session->tr, s, seq->base.name, seq->start, seq->minvalue, seq->maxvalue, seq->increment, seq->cacheinc, seq->cycle, seq->bedropped);
654 return NULL;
655}
656
657static str
658alter_seq(mvc *sql, char *sname, char *seqname, sql_sequence *seq, const lng *val)
659{
660 sql_schema *s = NULL;
661 sql_sequence *nseq = NULL;
662
663 (void)seqname;
664 if (sname && !(s = mvc_bind_schema(sql, sname)))
665 throw(SQL,"sql.alter_seq", SQLSTATE(3F000) "ALTER SEQUENCE: no such schema '%s'", sname);
666 if (s == NULL)
667 s = cur_schema(sql);
668 if (!(nseq = find_sql_sequence(s, seq->base.name)))
669 throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: no such sequence '%s'", seq->base.name);
670 else if (!mvc_schema_privs(sql, s))
671 throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: insufficient privileges for '%s' in schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
672 /* if seq properties hold NULL values, then they should be ignored during the update */
673 /* first alter the known values */
674 sql_trans_alter_sequence(sql->session->tr, nseq, seq->minvalue, seq->maxvalue, seq->increment, seq->cacheinc, seq->cycle);
675 if (nseq->minvalue && nseq->maxvalue && nseq->maxvalue < seq->minvalue)
676 throw(SQL, "sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: maximum value is lesser than the minimum ("LLFMT" < "LLFMT")", nseq->maxvalue, nseq->minvalue);
677 if (val) {
678 if (is_lng_nil(*val))
679 throw(SQL, "sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: sequence value must be non-NULL");
680 else if (nseq->minvalue && *val < nseq->minvalue)
681 throw(SQL, "sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: cannot set sequence start to a value lesser than the minimum ("LLFMT" < "LLFMT")", *val, nseq->minvalue);
682 else if (nseq->maxvalue && *val > nseq->maxvalue)
683 throw(SQL, "sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: cannot set sequence start to a value higher than the maximum ("LLFMT" > "LLFMT")", *val, nseq->maxvalue);
684 else if (!sql_trans_sequence_restart(sql->session->tr, nseq, *val))
685 throw(SQL, "sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: failed to restart sequence %s.%s", sname, nseq->base.name);
686 }
687 return MAL_SUCCEED;
688}
689
690static str
691drop_seq(mvc *sql, char *sname, char *name)
692{
693 sql_schema *s = NULL;
694 sql_sequence *seq = NULL;
695
696 if (sname && !(s = mvc_bind_schema(sql, sname)))
697 throw(SQL,"sql.drop_seq", SQLSTATE(3F000) "DROP SEQUENCE: no such schema '%s'", sname);
698 if (!s)
699 s = cur_schema(sql);
700 if (!(seq = find_sql_sequence(s, name))) {
701 throw(SQL,"sql.drop_seq", SQLSTATE(42M35) "DROP SEQUENCE: no such sequence '%s'", name);
702 } else if (!mvc_schema_privs(sql, s)) {
703 throw(SQL,"sql.drop_seq", SQLSTATE(42000) "DROP SEQUENCE: insufficient privileges for '%s' in schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
704 }
705 if (mvc_check_dependency(sql, seq->base.id, BEDROPPED_DEPENDENCY, NULL))
706 throw(SQL,"sql.drop_seq", SQLSTATE(2B000) "DROP SEQUENCE: unable to drop sequence %s (there are database objects which depend on it)\n", seq->base.name);
707
708 sql_trans_drop_sequence(sql->session->tr, s, seq, 0);
709 return NULL;
710}
711
712static str
713drop_func(mvc *sql, char *sname, char *name, sqlid fid, sql_ftype type, int action)
714{
715 sql_schema *s = NULL;
716 char is_aggr = (type == F_AGGR);
717 char is_func = (type != F_PROC);
718 char *F = is_aggr ? "AGGREGATE" : (is_func ? "FUNCTION" : "PROCEDURE");
719 char *f = is_aggr ? "aggregate" : (is_func ? "function" : "procedure");
720 char *KF = type == F_FILT ? "FILTER " : type == F_UNION ? "UNION " : "";
721 char *kf = type == F_FILT ? "filter " : type == F_UNION ? "union " : "";
722
723 if (sname && !(s = mvc_bind_schema(sql, sname)))
724 throw(SQL,"sql.drop_func", SQLSTATE(3F000) "DROP %s%s: no such schema '%s'", KF, F, sname);
725 if (!s)
726 s = cur_schema(sql);
727 if (fid >= 0) {
728 node *n = find_sql_func_node(s, fid);
729 if (n) {
730 sql_func *func = n->data;
731
732 if (!mvc_schema_privs(sql, s)) {
733 throw(SQL,"sql.drop_func", SQLSTATE(42000) "DROP %s%s: access denied for %s to schema '%s'", KF, F, stack_get_string(sql, "current_user"), s->base.name);
734 }
735 if (!action && mvc_check_dependency(sql, func->base.id, !IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY, NULL))
736 throw(SQL,"sql.drop_func", SQLSTATE(42000) "DROP %s%s: there are database objects dependent on %s%s %s;", KF, F, kf, f, func->base.name);
737
738 if(mvc_drop_func(sql, s, func, action))
739 throw(SQL,"sql.drop_func", SQLSTATE(HY001) MAL_MALLOC_FAIL);
740 }
741 } else if(fid == -2) { //if exists option
742 return MAL_SUCCEED;
743 } else { //fid == -1
744 node *n = NULL;
745 list *list_func = schema_bind_func(sql, s, name, type);
746 int res;
747
748 if (!mvc_schema_privs(sql, s)) {
749 list_destroy(list_func);
750 throw(SQL,"sql.drop_func", SQLSTATE(42000) "DROP %s%s: access denied for %s to schema '%s'", KF, F, stack_get_string(sql, "current_user"), s->base.name);
751 }
752 for (n = list_func->h; n; n = n->next) {
753 sql_func *func = n->data;
754
755 if (!action && mvc_check_dependency(sql, func->base.id, !IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY, list_func)) {
756 list_destroy(list_func);
757 throw(SQL,"sql.drop_func", SQLSTATE(42000) "DROP %s%s: there are database objects dependent on %s%s %s;", KF, F, kf, f, func->base.name);
758 }
759 }
760 res = mvc_drop_all_func(sql, s, list_func, action);
761 list_destroy(list_func);
762 if(res)
763 throw(SQL,"sql.drop_func", SQLSTATE(HY001) MAL_MALLOC_FAIL);
764 }
765 return MAL_SUCCEED;
766}
767
768static char *
769create_func(mvc *sql, char *sname, char *fname, sql_func *f)
770{
771 sql_func *nf;
772 sql_schema *s = NULL;
773 char is_aggr = (f->type == F_AGGR);
774 char is_func = (f->type != F_PROC);
775 char *F = is_aggr ? "AGGREGATE" : (is_func ? "FUNCTION" : "PROCEDURE");
776 char *KF = f->type == F_FILT ? "FILTER " : f->type == F_UNION ? "UNION " : "";
777
778 (void)fname;
779 if (sname && !(s = mvc_bind_schema(sql, sname)))
780 throw(SQL,"sql.create_func", SQLSTATE(3F000) "CREATE %s%s: no such schema '%s'", KF, F, sname);
781 if (!s)
782 s = cur_schema(sql);
783 nf = mvc_create_func(sql, NULL, s, f->base.name, f->ops, f->res, f->type, f->lang, f->mod, f->imp, f->query, f->varres, f->vararg, f->system);
784 assert(nf);
785 switch (nf->lang) {
786 case FUNC_LANG_INT:
787 case FUNC_LANG_MAL: /* shouldn't be reachable, but leave it here */
788 if (!backend_resolve_function(sql, nf))
789 throw(SQL,"sql.create_func", SQLSTATE(3F000) "CREATE %s%s: external name %s.%s not bound", KF, F, nf->mod, nf->base.name);
790 if (nf->query == NULL)
791 break;
792 /* fall through */
793 case FUNC_LANG_SQL: {
794 char *buf;
795 sql_rel *r = NULL;
796 sql_allocator *sa = sql->sa;
797
798 assert(nf->query);
799 if (!(sql->sa = sa_create()))
800 throw(SQL, "sql.catalog", SQLSTATE(HY001) MAL_MALLOC_FAIL);
801 if (!(buf = sa_strdup(sql->sa, nf->query)))
802 throw(SQL, "sql.catalog", SQLSTATE(HY001) MAL_MALLOC_FAIL);
803 r = rel_parse(sql, s, buf, m_deps);
804 if (r)
805 r = rel_unnest(sql, r);
806 if (r)
807 r = rel_optimizer(sql, r, 0);
808 if (r) {
809 node *n;
810 list *id_l = rel_dependencies(sql, r);
811
812 if (!f->vararg && f->ops) {
813 for (n = f->ops->h; n; n = n->next) {
814 sql_arg *a = n->data;
815
816 if (a->type.type->s)
817 mvc_create_dependency(sql, a->type.type->base.id, nf->base.id, TYPE_DEPENDENCY);
818 }
819 }
820 if (!f->varres && f->res) {
821 for (n = f->res->h; n; n = n->next) {
822 sql_arg *a = n->data;
823
824 if (a->type.type->s)
825 mvc_create_dependency(sql, a->type.type->base.id, nf->base.id, TYPE_DEPENDENCY);
826 }
827 }
828 mvc_create_dependencies(sql, id_l, nf->base.id, !IS_PROC(f) ? FUNC_DEPENDENCY : PROC_DEPENDENCY);
829 }
830 sa_destroy(sql->sa);
831 sql->sa = sa;
832 }
833 default:
834 break;
835 }
836 return MAL_SUCCEED;
837}
838
839static str
840alter_table(Client cntxt, mvc *sql, char *sname, sql_table *t)
841{
842 sql_schema *s = mvc_bind_schema(sql, sname);
843 sql_table *nt = NULL;
844 node *n;
845
846 if (!s)
847 throw(SQL,"sql.alter_table", SQLSTATE(3F000) "ALTER TABLE: no such schema '%s'", sname);
848
849 if ((nt = mvc_bind_table(sql, s, t->base.name)) == NULL) {
850 throw(SQL,"sql.alter_table", SQLSTATE(42S02) "ALTER TABLE: no such table '%s'", t->base.name);
851 } else if (!mvc_schema_privs(sql, s) && !(isTempSchema(s) && t->persistence == SQL_LOCAL_TEMP)) {
852 throw(SQL,"sql.alter_table", SQLSTATE(42000) "ALTER TABLE: insufficient privileges for user '%s' in schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
853 }
854
855 /* First check if all the changes are allowed */
856 if (t->idxs.set) {
857 /* only one pkey */
858 if (nt->pkey) {
859 for (n = t->idxs.nelm; n; n = n->next) {
860 sql_idx *i = n->data;
861 if (i->key && i->key->type == pkey)
862 throw(SQL,"sql.alter_table", SQLSTATE(40000) "CONSTRAINT PRIMARY KEY: a table can have only one PRIMARY KEY\n");
863 }
864 }
865 }
866
867 /* check for changes */
868 if (t->columns.dset)
869 for (n = t->columns.dset->h; n; n = n->next) {
870 /* propagate alter table .. drop column */
871 sql_column *c = n->data;
872 sql_column *nc = mvc_bind_column(sql, nt, c->base.name);
873 if(mvc_drop_column(sql, nt, nc, c->drop_action))
874 throw(SQL,"sql.alter_table", SQLSTATE(HY001) MAL_MALLOC_FAIL);
875 }
876 /* check for changes on current cols */
877 for (n = t->columns.set->h; n != t->columns.nelm; n = n->next) {
878
879 /* null or default value changes */
880 sql_column *c = n->data;
881 sql_column *nc = mvc_bind_column(sql, nt, c->base.name);
882
883 if (c->null != nc->null && isTable(nt)) {
884 if (c->null && nt->pkey) { /* check for primary keys based on this column */
885 node *m;
886 for(m = nt->pkey->k.columns->h; m; m = m->next) {
887 sql_kc *kc = m->data;
888
889 if (kc->c->base.id == c->base.id)
890 throw(SQL,"sql.alter_table", SQLSTATE(40000) "NOT NULL CONSTRAINT: cannot change NOT NULL CONSTRAINT for column '%s' as its part of the PRIMARY KEY\n", c->base.name);
891 }
892 }
893 mvc_null(sql, nc, c->null);
894 /* for non empty check for nulls */
895 if (c->null == 0) {
896 const void *nilptr = ATOMnilptr(c->type.type->localtype);
897 rids *nils = table_funcs.rids_select(sql->session->tr, nc, nilptr, NULL, NULL);
898 int has_nils = !is_oid_nil(table_funcs.rids_next(nils));
899
900 table_funcs.rids_destroy(nils);
901 if (has_nils)
902 throw(SQL,"sql.alter_table", SQLSTATE(40002) "ALTER TABLE: NOT NULL constraint violated for column %s.%s", c->t->base.name, c->base.name);
903 }
904 }
905 if (c->def != nc->def)
906 mvc_default(sql, nc, c->def);
907
908 if (c->storage_type != nc->storage_type) {
909 if (c->t->access == TABLE_WRITABLE)
910 throw(SQL,"sql.alter_table", SQLSTATE(40002) "ALTER TABLE: SET STORAGE for column %s.%s only allowed on READ or INSERT ONLY tables", c->t->base.name, c->base.name);
911 nc->base.rtime = nc->base.wtime = sql->session->tr->wtime;
912 mvc_storage(sql, nc, c->storage_type);
913 }
914 }
915 for (; n; n = n->next) {
916 /* propagate alter table .. add column */
917 sql_column *c = n->data;
918
919 if (mvc_copy_column(sql, nt, c) == NULL)
920 throw(SQL,"sql.alter_table", SQLSTATE(40002) "ALTER TABLE: Failed to create column %s.%s", c->t->base.name, c->base.name);
921 }
922 if (t->idxs.set) {
923 /* alter drop index */
924 if (t->idxs.dset)
925 for (n = t->idxs.dset->h; n; n = n->next) {
926 sql_idx *i = n->data;
927 sql_idx *ni = mvc_bind_idx(sql, s, i->base.name);
928 if(mvc_drop_idx(sql, s, ni))
929 throw(SQL,"sql.alter_table", SQLSTATE(HY001) MAL_MALLOC_FAIL);
930 }
931 /* alter add index */
932 for (n = t->idxs.nelm; n; n = n->next) {
933 sql_idx *i = n->data;
934
935 if (i->type == ordered_idx) {
936 sql_kc *ic = i->columns->h->data;
937 BAT *b = mvc_bind(sql, nt->s->base.name, nt->base.name, ic->c->base.name, 0);
938 char *msg = OIDXcreateImplementation(cntxt, newBatType(b->ttype), b, -1);
939 BBPunfix(b->batCacheid);
940 if (msg != MAL_SUCCEED) {
941 char *smsg = createException(SQL,"sql.alter_table", SQLSTATE(40002) "CREATE ORDERED INDEX: %s", msg);
942 freeException(msg);
943 return smsg;
944 }
945 }
946 if (i->type == imprints_idx) {
947 gdk_return r;
948 sql_kc *ic = i->columns->h->data;
949 BAT *b = mvc_bind(sql, nt->s->base.name, nt->base.name, ic->c->base.name, 0);
950 r = BATimprints(b);
951 BBPunfix(b->batCacheid);
952 if (r != GDK_SUCCEED)
953 throw(SQL, "sql.alter_table", GDK_EXCEPTION);
954 }
955 if (mvc_copy_idx(sql, nt, i) == NULL)
956 throw(SQL,"sql.alter_table", SQLSTATE(40002) "ALTER TABLE: Failed to create index %s.%s", i->t->base.name, i->base.name);
957 }
958 }
959 if (t->keys.set) {
960 /* alter drop key */
961 if (t->keys.dset)
962 for (n = t->keys.dset->h; n; n = n->next) {
963 sql_key *k = n->data;
964 sql_key *nk = mvc_bind_key(sql, s, k->base.name);
965 if (nk) {
966 if(mvc_drop_key(sql, s, nk, k->drop_action))
967 throw(SQL,"sql.alter_table", SQLSTATE(HY001) MAL_MALLOC_FAIL);
968 }
969 }
970 /* alter add key */
971 for (n = t->keys.nelm; n; n = n->next) {
972 sql_key *k = n->data;
973 str err;
974 if((err = sql_partition_validate_key(sql, t, k, "ALTER")))
975 return err;
976 mvc_copy_key(sql, nt, k);
977 }
978 }
979 return MAL_SUCCEED;
980}
981
982/* the MAL wrappers */
983str
984SQLcreate_seq(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
985{ mvc *sql = NULL;
986 str msg;
987 str sname = *getArgReference_str(stk, pci, 1);
988 str seqname = *getArgReference_str(stk, pci, 2);
989 sql_sequence *s = *(sql_sequence **) getArgReference(stk, pci, 3);
990
991 initcontext();
992 msg = create_seq(sql, sname, seqname, s);
993 return msg;
994}
995
996str
997SQLalter_seq(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
998{ mvc *sql = NULL;
999 str msg = MAL_SUCCEED;
1000 str sname = *getArgReference_str(stk, pci, 1);
1001 str seqname = *getArgReference_str(stk, pci, 2);
1002 sql_sequence *s = *(sql_sequence **) getArgReference(stk, pci, 3);
1003 lng *val = NULL;
1004
1005 initcontext();
1006 if (getArgType(mb, pci, 4) == TYPE_lng)
1007 val = getArgReference_lng(stk, pci, 4);
1008 if (val == NULL || is_lng_nil(*val))
1009 msg = createException(SQL,"sql.alter_seq", SQLSTATE(42M36) "ALTER SEQUENCE: cannot (re)start with NULL");
1010 else
1011 msg = alter_seq(sql, sname, seqname, s, val);
1012 return msg;
1013}
1014
1015str
1016SQLdrop_seq(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1017{ mvc *sql = NULL;
1018 str msg = MAL_SUCCEED;
1019 str sname = *getArgReference_str(stk, pci, 1);
1020 str name = *getArgReference_str(stk, pci, 2);
1021
1022 initcontext();
1023 msg = drop_seq(sql, sname, name);
1024 return msg;
1025}
1026
1027str
1028SQLcreate_schema(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1029{ mvc *sql = NULL;
1030 str msg = MAL_SUCCEED;
1031 str sname = *getArgReference_str(stk, pci, 1);
1032 str name = SaveArgReference(stk, pci, 2);
1033 sqlid auth_id;
1034
1035 initcontext();
1036 auth_id = sql->role_id;
1037 if (name && (auth_id = sql_find_auth(sql, name)) < 0) {
1038 throw(SQL,"sql.create_schema", SQLSTATE(42M32) "CREATE SCHEMA: no such authorization '%s'", name);
1039 }
1040 if (sql->user_id != USER_MONETDB && sql->role_id != ROLE_SYSADMIN) {
1041 throw(SQL,"sql.create_schema", SQLSTATE(42000) "CREATE SCHEMA: insufficient privileges for user '%s'", stack_get_string(sql, "current_user"));
1042 }
1043 if (mvc_bind_schema(sql, sname)) {
1044 throw(SQL,"sql.create_schema", SQLSTATE(3F000) "CREATE SCHEMA: name '%s' already in use", sname);
1045 } else {
1046 (void) mvc_create_schema(sql, sname, auth_id, sql->user_id);
1047 }
1048 return msg;
1049}
1050
1051str
1052SQLdrop_schema(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1053{ mvc *sql = NULL;
1054 str msg= MAL_SUCCEED;
1055 str sname = *getArgReference_str(stk, pci, 1);
1056 str notused = *getArgReference_str(stk, pci, 2);
1057 int if_exists = *getArgReference_int(stk, pci, 3);
1058 int action = *getArgReference_int(stk, pci, 4);
1059 sql_schema *s;
1060
1061 (void) notused;
1062 initcontext();
1063 s = mvc_bind_schema(sql, sname);
1064 if (!s) {
1065 if(!if_exists)
1066 throw(SQL,"sql.drop_schema",SQLSTATE(3F000) "DROP SCHEMA: name %s does not exist", sname);
1067 } else if (!mvc_schema_privs(sql, s)) {
1068 throw(SQL,"sql.drop_schema",SQLSTATE(42000) "DROP SCHEMA: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
1069 } else if (s == cur_schema(sql)) {
1070 throw(SQL,"sql.drop_schema",SQLSTATE(42000) "DROP SCHEMA: cannot drop current schema");
1071 } else if (s->system) {
1072 throw(SQL,"sql.drop_schema",SQLSTATE(42000) "DROP SCHEMA: access denied for '%s'", sname);
1073 } else if (sql_schema_has_user(sql, s)) {
1074 throw(SQL,"sql.drop_schema",SQLSTATE(2BM37) "DROP SCHEMA: unable to drop schema '%s' (there are database objects which depend on it)", sname);
1075 } else if (!action /* RESTRICT */ && (
1076 !list_empty(s->tables.set) || !list_empty(s->types.set) ||
1077 !list_empty(s->funcs.set) || !list_empty(s->seqs.set))) {
1078 throw(SQL,"sql.drop_schema",SQLSTATE(2BM37) "DROP SCHEMA: unable to drop schema '%s' (there are database objects which depend on it)", sname);
1079 } else {
1080 if(mvc_drop_schema(sql, s, action))
1081 throw(SQL,"sql.drop_schema", SQLSTATE(HY001) MAL_MALLOC_FAIL);
1082 }
1083 return msg;
1084}
1085
1086str
1087SQLcreate_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1088{ mvc *sql = NULL;
1089 str msg;
1090 str sname = *getArgReference_str(stk, pci, 1);
1091 //str tname = *getArgReference_str(stk, pci, 2);
1092 sql_table *t = *(sql_table **) getArgReference(stk, pci, 3);
1093 int temp = *getArgReference_int(stk, pci, 4);
1094
1095 initcontext();
1096 msg = create_table_or_view(sql, sname, t->base.name, t, temp);
1097 return msg;
1098}
1099
1100str
1101SQLcreate_view(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1102{ mvc *sql = NULL;
1103 str msg;
1104 str sname = *getArgReference_str(stk, pci, 1);
1105 //str vname = *getArgReference_str(stk, pci, 2);
1106 sql_table *t = *(sql_table **) getArgReference(stk, pci, 3);
1107 int temp = *getArgReference_int(stk, pci, 4);
1108
1109 initcontext();
1110 msg = create_table_or_view(sql, sname, t->base.name, t, temp);
1111 return msg;
1112}
1113
1114str
1115SQLdrop_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1116{ mvc *sql = NULL;
1117 str msg;
1118 str sname = *getArgReference_str(stk, pci, 1);
1119 str name = *getArgReference_str(stk, pci, 2);
1120 int if_exists = *getArgReference_int(stk, pci, 3);
1121 int action = *getArgReference_int(stk, pci, 4);
1122
1123 initcontext();
1124 msg = drop_table(sql, sname, name, action, if_exists);
1125 return msg;
1126}
1127
1128str
1129SQLdrop_view(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1130{ mvc *sql = NULL;
1131 str msg;
1132 str sname = *getArgReference_str(stk, pci, 1);
1133 str name = *getArgReference_str(stk, pci, 2);
1134 int if_exists = *getArgReference_int(stk, pci, 3);
1135 int action = *getArgReference_int(stk, pci, 4);
1136
1137 initcontext();
1138 msg = drop_view(sql, sname, name, action, if_exists);
1139 return msg;
1140}
1141
1142str
1143SQLdrop_constraint(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1144{ mvc *sql = NULL;
1145 str msg;
1146 str sname = *getArgReference_str(stk, pci, 1);
1147 str name = *getArgReference_str(stk, pci, 2);
1148 int action = *getArgReference_int(stk, pci, 4);
1149 (void) *getArgReference_int(stk, pci, 3); //the if_exists parameter is also passed but not used
1150
1151 initcontext();
1152 msg = drop_key(sql, sname, name, action);
1153 return msg;
1154}
1155
1156str
1157SQLalter_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1158{ mvc *sql = NULL;
1159 str msg;
1160 str sname = *getArgReference_str(stk, pci, 1);
1161 str tname = *getArgReference_str(stk, pci, 2);
1162 sql_table *t = *(sql_table **) getArgReference(stk, pci, 3);
1163
1164 (void)tname;
1165 initcontext();
1166 msg = alter_table(cntxt, sql, sname, t);
1167 return msg;
1168}
1169
1170str
1171SQLcreate_type(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1172{ mvc *sql = NULL;
1173 str msg;
1174 str sname = *getArgReference_str(stk, pci, 1);
1175 char *name = *getArgReference_str(stk, pci, 2);
1176 char *impl = *getArgReference_str(stk, pci, 3);
1177 sql_schema *s = NULL;
1178
1179 initcontext();
1180
1181 if (sname && !(s = mvc_bind_schema(sql, sname)))
1182 throw(SQL,"sql.create_type",SQLSTATE(3F000) "CREATE TYPE: no such schema '%s'", sname);
1183 if (!s)
1184 s = cur_schema(sql);
1185
1186 if (!mvc_schema_privs(sql, s))
1187 throw(SQL,"sql.create_type", SQLSTATE(42000) "CREATE TYPE: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
1188 if (schema_bind_type(sql, s, name))
1189 throw(SQL,"sql.create_type", SQLSTATE(42S02) "CREATE TYPE: type '%s' already exists", name);
1190 if (!mvc_create_type(sql, s, name, 0, 0, 0, impl))
1191 throw(SQL,"sql.create_type", SQLSTATE(0D000) "CREATE TYPE: unknown external type '%s'", impl);
1192 return msg;
1193}
1194
1195str
1196SQLdrop_type(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1197{ mvc *sql = NULL;
1198 str msg;
1199 str sname = *getArgReference_str(stk, pci, 1);
1200 char *name = *getArgReference_str(stk, pci, 2);
1201 int drop_action = *getArgReference_int(stk, pci, 3);
1202 sql_schema *s = NULL;
1203 sql_type *t;
1204
1205 initcontext();
1206
1207 if (sname && !(s = mvc_bind_schema(sql, sname)))
1208 throw(SQL,"sql.drop_type",SQLSTATE(3F000) "DROP TYPE: no such schema '%s'", sname);
1209 if (!s)
1210 s = cur_schema(sql);
1211
1212 if (!mvc_schema_privs(sql, s))
1213 throw(SQL,"sql.drop_type", SQLSTATE(42000) "DROP TYPE: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
1214 else if (!(t = schema_bind_type(sql, s, name)))
1215 throw(SQL,"sql.drop_type", SQLSTATE(3F000) "DROP TYPE: type '%s' does not exist", name);
1216 else if (!drop_action && mvc_check_dependency(sql, t->base.id, TYPE_DEPENDENCY, NULL))
1217 throw(SQL,"sql.drop_type", SQLSTATE(42000) "DROP TYPE: unable to drop type %s (there are database objects which depend on it)\n", name);
1218 else if (!mvc_drop_type(sql, s, t, drop_action))
1219 throw(SQL,"sql.drop_type", SQLSTATE(0D000) "DROP TYPE: failed to drop type '%s'", name);
1220 return msg;
1221}
1222
1223str
1224SQLgrant_roles(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1225{ mvc *sql = NULL;
1226 str msg;
1227 str sname = *getArgReference_str(stk, pci, 1);
1228 char *auth = SaveArgReference(stk, pci, 2);
1229 sqlid grantor = (sqlid) *getArgReference_int(stk, pci, 3);
1230 int admin = *getArgReference_int(stk, pci, 4);
1231
1232 initcontext();
1233 msg = sql_grant_role(sql, sname /*grantee */ , auth, grantor, admin);
1234 return msg;
1235}
1236
1237str
1238SQLrevoke_roles(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1239{ mvc *sql = NULL;
1240 str msg;
1241 str sname = *getArgReference_str(stk, pci, 1);
1242 char *auth = SaveArgReference(stk, pci, 2);
1243 sqlid grantor = (sqlid) *getArgReference_int(stk, pci, 3);
1244 int admin = *getArgReference_int(stk, pci, 4);
1245
1246 initcontext();
1247 msg = sql_revoke_role(sql, sname /*grantee */ , auth, grantor, admin);
1248 return msg;
1249}
1250
1251str
1252SQLgrant(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1253{ mvc *sql = NULL;
1254 str msg;
1255 str sname = *getArgReference_str(stk, pci, 1);
1256 char *tname = *getArgReference_str(stk, pci, 2);
1257 char *grantee = *getArgReference_str(stk, pci, 3);
1258 int privs = *getArgReference_int(stk, pci, 4);
1259 char *cname = SaveArgReference(stk, pci, 5);
1260 int grant = *getArgReference_int(stk, pci, 6);
1261 sqlid grantor = (sqlid) *getArgReference_int(stk, pci, 7);
1262
1263 initcontext();
1264 if (!tname || strcmp(tname, str_nil) == 0)
1265 msg = sql_grant_global_privs(sql, grantee, privs, grant, grantor);
1266 else
1267 msg = sql_grant_table_privs(sql, grantee, privs, sname, tname, cname, grant, grantor);
1268 return msg;
1269}
1270
1271str SQLrevoke(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1272{ mvc *sql = NULL;
1273 str msg;
1274 str sname = *getArgReference_str(stk, pci, 1);
1275 char *tname = *getArgReference_str(stk, pci, 2);
1276 char *grantee = *getArgReference_str(stk, pci, 3);
1277 int privs = *getArgReference_int(stk, pci, 4);
1278 char *cname = SaveArgReference(stk, pci, 5);
1279 int grant = *getArgReference_int(stk, pci, 6);
1280 sqlid grantor = (sqlid) *getArgReference_int(stk, pci, 7);
1281
1282 initcontext();
1283 if (!tname || strcmp(tname, str_nil) == 0)
1284 msg = sql_revoke_global_privs(sql, grantee, privs, grant, grantor);
1285 else
1286 msg = sql_revoke_table_privs(sql, grantee, privs, sname, tname, cname, grant, grantor);
1287 return msg;
1288}
1289
1290str
1291SQLgrant_function(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1292{ mvc *sql = NULL;
1293 str msg;
1294 str sname = *getArgReference_str(stk, pci, 1);
1295 sqlid func_id = (sqlid) *getArgReference_int(stk, pci, 2);
1296 char *grantee = *getArgReference_str(stk, pci, 3);
1297 int privs = *getArgReference_int(stk, pci, 4);
1298 int grant = *getArgReference_int(stk, pci, 5);
1299 sqlid grantor = (sqlid) *getArgReference_int(stk, pci, 6);
1300
1301 initcontext();
1302 msg = sql_grant_func_privs(sql, grantee, privs, sname, func_id, grant, grantor);
1303 return msg;
1304}
1305
1306str
1307SQLrevoke_function(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1308{ mvc *sql = NULL;
1309 str msg;
1310 str sname = *getArgReference_str(stk, pci, 1);
1311 sqlid func_id = (sqlid) *getArgReference_int(stk, pci, 2);
1312 char *grantee = *getArgReference_str(stk, pci, 3);
1313 int privs = *getArgReference_int(stk, pci, 4);
1314 int grant = *getArgReference_int(stk, pci, 5);
1315 sqlid grantor = (sqlid) *getArgReference_int(stk, pci, 6);
1316
1317 initcontext();
1318 msg = sql_revoke_func_privs(sql, grantee, privs, sname, func_id, grant, grantor);
1319 return msg;
1320}
1321
1322str
1323SQLcreate_user(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1324{ mvc *sql = NULL;
1325 str msg;
1326 str sname = *getArgReference_str(stk, pci, 1);
1327 char *passwd = *getArgReference_str(stk, pci, 2);
1328 int enc = *getArgReference_int(stk, pci, 3);
1329 char *schema = SaveArgReference(stk, pci, 4);
1330 char *fullname = SaveArgReference(stk, pci, 5);
1331
1332 initcontext();
1333 msg = sql_create_user(sql, sname, passwd, enc, fullname, schema);
1334 return msg;
1335}
1336
1337str
1338SQLdrop_user(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1339{ mvc *sql = NULL;
1340 str msg;
1341 str sname = *getArgReference_str(stk, pci, 1);
1342
1343 initcontext();
1344 msg = sql_drop_user(sql, sname);
1345 return msg;
1346}
1347
1348str
1349SQLalter_user(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1350{ mvc *sql = NULL;
1351 str msg;
1352 str sname = *getArgReference_str(stk, pci, 1);
1353 char *passwd = SaveArgReference(stk, pci, 2);
1354 int enc = *getArgReference_int(stk, pci, 3);
1355 char *schema = SaveArgReference(stk, pci, 4);
1356 char *oldpasswd = SaveArgReference(stk, pci, 5);
1357
1358 initcontext();
1359 msg = sql_alter_user(sql, sname, passwd, enc, schema, oldpasswd);
1360
1361 return msg;
1362}
1363
1364str
1365SQLrename_user(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1366{ mvc *sql = NULL;
1367 str msg;
1368 str sname = *getArgReference_str(stk, pci, 1);
1369 char *newuser = *getArgReference_str(stk, pci, 2);
1370
1371 initcontext();
1372 msg = sql_rename_user(sql, sname, newuser);
1373 return msg;
1374}
1375
1376str
1377SQLcreate_role(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1378{ mvc *sql = NULL;
1379 str msg;
1380 str sname = *getArgReference_str(stk, pci, 1);
1381 char *role = sname;
1382 sqlid grantor = (sqlid)*getArgReference_int(stk, pci, 3);
1383
1384 initcontext();
1385 msg = sql_create_role(sql, role, grantor);
1386 return msg;
1387}
1388
1389str
1390SQLdrop_role(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1391{ mvc *sql = NULL;
1392 str msg;
1393 str sname = *getArgReference_str(stk, pci, 1);
1394 char *role = sname;
1395
1396 initcontext();
1397 msg = sql_drop_role(sql, role);
1398 return msg;
1399}
1400
1401str
1402SQLdrop_index(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1403{ mvc *sql = NULL;
1404 str msg;
1405 str sname = *getArgReference_str(stk, pci, 1);
1406 char *iname = *getArgReference_str(stk, pci, 2);
1407
1408 initcontext();
1409 msg = drop_index(cntxt, sql, sname, iname);
1410 return msg;
1411}
1412
1413str
1414SQLdrop_function(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1415{ mvc *sql = NULL;
1416 str msg;
1417 str sname = *getArgReference_str(stk, pci, 1);
1418 char *fname = *getArgReference_str(stk, pci, 2);
1419 sqlid fid = (sqlid)*getArgReference_int(stk, pci, 3);
1420 sql_ftype type = (sql_ftype) *getArgReference_int(stk, pci, 4);
1421 int action = *getArgReference_int(stk, pci, 5);
1422
1423 initcontext();
1424 msg = drop_func(sql, sname, fname, fid, type, action);
1425 return msg;
1426}
1427
1428str
1429SQLcreate_function(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1430{ mvc *sql = NULL;
1431 str msg;
1432 str sname = *getArgReference_str(stk, pci, 1);
1433 str fname = *getArgReference_str(stk, pci, 2);
1434 sql_func *f = *(sql_func **) getArgReference(stk, pci, 3);
1435
1436 initcontext();
1437 msg = create_func(sql, sname, fname, f);
1438 return msg;
1439}
1440
1441str
1442SQLcreate_trigger(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1443{ mvc *sql = NULL;
1444 str msg;
1445 str sname = *getArgReference_str(stk, pci, 1);
1446 char *tname = *getArgReference_str(stk, pci, 2);
1447 char *triggername = *getArgReference_str(stk, pci, 3);
1448 int time = *getArgReference_int(stk, pci, 4);
1449 int orientation = *getArgReference_int(stk, pci, 5);
1450 int event = *getArgReference_int(stk, pci, 6);
1451 char *old_name = *getArgReference_str(stk, pci, 7);
1452 char *new_name = *getArgReference_str(stk, pci, 8);
1453 char *condition = *getArgReference_str(stk, pci, 9);
1454 char *query = *getArgReference_str(stk, pci, 10);
1455
1456 initcontext();
1457 old_name=(!old_name || strcmp(old_name, str_nil) == 0)?NULL:old_name;
1458 new_name=(!new_name || strcmp(new_name, str_nil) == 0)?NULL:new_name;
1459 condition=(!condition || strcmp(condition, str_nil) == 0)?NULL:condition;
1460 msg = create_trigger(sql, sname, tname, triggername, time, orientation, event, old_name, new_name, condition, query);
1461 return msg;
1462}
1463
1464str
1465SQLdrop_trigger(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1466{ mvc *sql = NULL;
1467 str msg;
1468 str sname = *getArgReference_str(stk, pci, 1);
1469 char *triggername = *getArgReference_str(stk, pci, 2);
1470 int if_exists = *getArgReference_int(stk, pci, 3);
1471
1472 initcontext();
1473 msg = drop_trigger(sql, sname, triggername, if_exists);
1474 return msg;
1475}
1476
1477str
1478SQLalter_add_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1479{ mvc *sql = NULL;
1480 str msg;
1481 str sname = *getArgReference_str(stk, pci, 1);
1482 char *mtname = SaveArgReference(stk, pci, 2);
1483 char *psname = SaveArgReference(stk, pci, 3);
1484 char *ptname = SaveArgReference(stk, pci, 4);
1485
1486 initcontext();
1487 msg = alter_table_add_table(sql, sname, mtname, psname, ptname);
1488 return msg;
1489}
1490
1491str
1492SQLalter_add_range_partition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1493{ mvc *sql = NULL;
1494 str msg;
1495 str sname = *getArgReference_str(stk, pci, 1);
1496 char *mtname = SaveArgReference(stk, pci, 2);
1497 char *psname = SaveArgReference(stk, pci, 3);
1498 char *ptname = SaveArgReference(stk, pci, 4);
1499 ValRecord *min = &(stk)->stk[(pci)->argv[5]];
1500 ValRecord *max = &(stk)->stk[(pci)->argv[6]];
1501 int with_nills = *getArgReference_int(stk, pci, 7);
1502 int update = *getArgReference_int(stk, pci, 8);
1503
1504 initcontext();
1505 msg = alter_table_add_range_partition(sql, sname, mtname, psname, ptname, VALget(min), VALget(max), with_nills, update);
1506 return msg;
1507}
1508
1509str
1510SQLalter_add_value_partition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1511{ mvc *sql = NULL;
1512 str msg;
1513 str sname = *getArgReference_str(stk, pci, 1);
1514 char *mtname = SaveArgReference(stk, pci, 2);
1515 char *psname = SaveArgReference(stk, pci, 3);
1516 char *ptname = SaveArgReference(stk, pci, 4);
1517 int with_nills = *getArgReference_int(stk, pci, 5);
1518 int update = *getArgReference_int(stk, pci, 6);
1519
1520 initcontext();
1521 msg = alter_table_add_value_partition(sql, stk, pci, sname, mtname, psname, ptname, with_nills, update);
1522 return msg;
1523}
1524
1525str
1526SQLalter_del_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1527{ mvc *sql = NULL;
1528 str msg;
1529 str sname = *getArgReference_str(stk, pci, 1);
1530 char *mtname = SaveArgReference(stk, pci, 2);
1531 char *psname = SaveArgReference(stk, pci, 3);
1532 char *ptname = SaveArgReference(stk, pci, 4);
1533 int drop_action = *getArgReference_int(stk, pci, 5);
1534
1535 initcontext();
1536 msg= alter_table_del_table(sql, sname, mtname, psname, ptname, drop_action);
1537 return msg;
1538}
1539
1540str
1541SQLalter_set_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1542{ mvc *sql = NULL;
1543 str msg;
1544 str sname = *getArgReference_str(stk, pci, 1);
1545 char *tname = SaveArgReference(stk, pci, 2);
1546 int access = *getArgReference_int(stk, pci, 3);
1547
1548 initcontext();
1549 msg = alter_table_set_access(sql, sname, tname, access);
1550
1551 return msg;
1552}
1553
1554str
1555SQLcomment_on(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1556{
1557 mvc *sql = NULL;
1558 str msg;
1559 sqlid objid = (sqlid) *getArgReference_int(stk, pci, 1);
1560 char *remark = *getArgReference_str(stk, pci, 2);
1561 sql_trans *tx;
1562 sql_schema *sys;
1563 sql_table *comments;
1564 sql_column *id_col, *remark_col;
1565 oid rid;
1566 int ok = LOG_OK;
1567
1568 initcontext();
1569
1570 // Manually insert the rows to circumvent permission checks.
1571 tx = sql->session->tr;
1572 sys = mvc_bind_schema(sql, "sys");
1573 if (!sys)
1574 throw(SQL, "sql.comment_on", SQLSTATE(3F000) "Internal error");
1575 comments = mvc_bind_table(sql, sys, "comments");
1576 if (!comments)
1577 throw(SQL, "sql.comment_on", SQLSTATE(3F000) "no table sys.comments");
1578 id_col = mvc_bind_column(sql, comments, "id");
1579 remark_col = find_sql_column(comments, "remark");
1580 if (!id_col || !remark_col)
1581 throw(SQL, "sql.comment_on", SQLSTATE(3F000) "no table sys.comments");
1582 rid = table_funcs.column_find_row(tx, id_col, &objid, NULL);
1583 if (remark != NULL && *remark && strcmp(remark, str_nil) != 0) {
1584 if (!is_oid_nil(rid)) {
1585 // have new remark and found old one, so update field
1586 /* UPDATE sys.comments SET remark = %s WHERE id = %d */
1587 ok = table_funcs.column_update_value(tx, remark_col, rid, remark);
1588 } else {
1589 // have new remark but found none so insert row
1590 /* INSERT INTO sys.comments (id, remark) VALUES (%d, %s) */
1591 ok = table_funcs.table_insert(tx, comments, &objid, remark);
1592 }
1593 } else {
1594 if (!is_oid_nil(rid)) {
1595 // have no remark but found one, so delete row
1596 /* DELETE FROM sys.comments WHERE id = %d */
1597 ok = table_funcs.table_delete(tx, comments, rid);
1598 }
1599 }
1600 if (ok != LOG_OK)
1601 throw(SQL, "sql.comment_on", SQLSTATE(3F000) "operation failed");
1602 return MAL_SUCCEED;
1603}
1604
1605str
1606SQLrename_schema(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1607{
1608 mvc *sql = NULL;
1609 str msg = MAL_SUCCEED;
1610 str old_name = *getArgReference_str(stk, pci, 1);
1611 str new_name = *getArgReference_str(stk, pci, 2);
1612 sql_schema *s;
1613
1614 initcontext();
1615 if (!(s = mvc_bind_schema(sql, old_name)))
1616 throw(SQL, "sql.rename_schema", SQLSTATE(42S02) "ALTER SCHEMA: no such schema '%s'", old_name);
1617 if (!mvc_schema_privs(sql, s))
1618 throw(SQL, "sql.rename_schema", SQLSTATE(3F000) "ALTER SCHEMA: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), old_name);
1619 if (s->system)
1620 throw(SQL, "sql.rename_schema", SQLSTATE(3F000) "ALTER SCHEMA: cannot rename a system schema");
1621 if (!list_empty(s->tables.set) || !list_empty(s->types.set) || !list_empty(s->funcs.set) || !list_empty(s->seqs.set))
1622 throw(SQL, "sql.rename_schema", SQLSTATE(2BM37) "ALTER SCHEMA: unable to rename schema '%s' (there are database objects which depend on it)", old_name);
1623 if (!new_name || strcmp(new_name, str_nil) == 0 || *new_name == '\0')
1624 throw(SQL, "sql.rename_schema", SQLSTATE(3F000) "ALTER SCHEMA: invalid new schema name");
1625 if (mvc_bind_schema(sql, new_name))
1626 throw(SQL, "sql.rename_schema", SQLSTATE(3F000) "ALTER SCHEMA: there is a schema named '%s' in the database", new_name);
1627
1628 if (!sql_trans_rename_schema(sql->session->tr, s->base.id, new_name))
1629 throw(SQL, "sql.rename_schema",SQLSTATE(HY001) MAL_MALLOC_FAIL);
1630 if (s == cur_schema(sql))
1631 if(!mvc_set_schema(sql, new_name))
1632 throw(SQL, "sql.rename_schema",SQLSTATE(HY001) MAL_MALLOC_FAIL);
1633 return msg;
1634}
1635
1636str
1637SQLrename_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1638{
1639 mvc *sql = NULL;
1640 str msg = MAL_SUCCEED;
1641 str oschema_name = *getArgReference_str(stk, pci, 1);
1642 str nschema_name = *getArgReference_str(stk, pci, 2);
1643 str otable_name = *getArgReference_str(stk, pci, 3);
1644 str ntable_name = *getArgReference_str(stk, pci, 4);
1645 sql_schema *o, *s;
1646 sql_table *t;
1647
1648 initcontext();
1649
1650 if(strcmp(oschema_name, nschema_name) == 0) { //renaming the table itself
1651 if (!(s = mvc_bind_schema(sql, oschema_name)))
1652 throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no such schema '%s'", oschema_name);
1653 if (!mvc_schema_privs(sql, s))
1654 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), oschema_name);
1655 if (!(t = mvc_bind_table(sql, s, otable_name)))
1656 throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", otable_name, oschema_name);
1657 if (t->system)
1658 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: cannot rename a system table");
1659 if (mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY, NULL))
1660 throw (SQL,"sql.rename_table", SQLSTATE(2BM37) "ALTER TABLE: unable to rename table '%s' (there are database objects which depend on it)", otable_name);
1661 if (!ntable_name || strcmp(ntable_name, str_nil) == 0 || *ntable_name == '\0')
1662 throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER TABLE: invalid new table name");
1663 if (mvc_bind_table(sql, s, ntable_name))
1664 throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER TABLE: there is a table named '%s' in schema '%s'", ntable_name, oschema_name);
1665
1666 if (!sql_trans_rename_table(sql->session->tr, s, t->base.id, ntable_name))
1667 throw(SQL, "sql.rename_table",SQLSTATE(HY001) MAL_MALLOC_FAIL);
1668 } else { //changing the schema of the table
1669 assert(strcmp(otable_name, ntable_name) == 0);
1670
1671 if (!(o = mvc_bind_schema(sql, oschema_name)))
1672 throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no such schema '%s'", oschema_name);
1673 if (!mvc_schema_privs(sql, o))
1674 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), oschema_name);
1675 if (!(t = mvc_bind_table(sql, o, otable_name)))
1676 throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", otable_name, oschema_name);
1677 if (t->system)
1678 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: cannot set schema of a system table");
1679 if (isTempSchema(o) || isTempTable(t))
1680 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: not possible to change a temporary table schema");
1681 if (isView(t))
1682 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: not possible to change schema of a view");
1683 if (mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY, NULL))
1684 throw(SQL, "sql.rename_table", SQLSTATE(2BM37) "ALTER TABLE: unable to set schema of table '%s' (there are database objects which depend on it)", otable_name);
1685 if (t->members.set || t->triggers.set)
1686 throw(SQL, "sql.rename_table", SQLSTATE(2BM37) "ALTER TABLE: unable to set schema of table '%s' (there are database objects which depend on it)", otable_name);
1687 if (!(s = mvc_bind_schema(sql, nschema_name)))
1688 throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no such schema '%s'", nschema_name);
1689 if (!mvc_schema_privs(sql, s))
1690 throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE: access denied for '%s' to schema '%s'", stack_get_string(sql, "current_user"), nschema_name);
1691 if (isTempSchema(s))
1692 throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER TABLE: not possible to change table's schema to temporary");
1693 if (mvc_bind_table(sql, s, otable_name))
1694 throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: table '%s' on schema '%s' already exists", otable_name, nschema_name);
1695
1696 if (!sql_trans_set_table_schema(sql->session->tr, t->base.id, o, s))
1697 throw(SQL, "sql.rename_table",SQLSTATE(HY001) MAL_MALLOC_FAIL);
1698 }
1699
1700 return msg;
1701}
1702
1703str
1704SQLrename_column(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1705{
1706 mvc *sql = NULL;
1707 str msg = MAL_SUCCEED;
1708 str schema_name = *getArgReference_str(stk, pci, 1);
1709 str table_name = *getArgReference_str(stk, pci, 2);
1710 str old_name = *getArgReference_str(stk, pci, 3);
1711 str new_name = *getArgReference_str(stk, pci, 4);
1712 sql_schema *s;
1713 sql_table *t;
1714 sql_column *col;
1715
1716 initcontext();
1717 if (!(s = mvc_bind_schema(sql, schema_name)))
1718 throw(SQL, "sql.rename_column", SQLSTATE(42S02) "ALTER TABLE: no such schema '%s'", schema_name);
1719 if (!mvc_schema_privs(sql, s))
1720 throw(SQL, "sql.rename_column", SQLSTATE(42000) "ALTER TABLE: access denied for %s to schema '%s'", stack_get_string(sql, "current_user"), schema_name);
1721 if (!(t = mvc_bind_table(sql, s, table_name)))
1722 throw(SQL, "sql.rename_column", SQLSTATE(42S02) "ALTER TABLE: no such table '%s' in schema '%s'", table_name, schema_name);
1723 if (t->system)
1724 throw(SQL, "sql.rename_column", SQLSTATE(42000) "ALTER TABLE: cannot rename a column in a system table");
1725 if (isView(t))
1726 throw(SQL, "sql.rename_column", SQLSTATE(42000) "ALTER TABLE: cannot rename column '%s': '%s' is a view", old_name, table_name);
1727 if (!(col = mvc_bind_column(sql, t, old_name)))
1728 throw(SQL, "sql.rename_column", SQLSTATE(42S22) "ALTER TABLE: no such column '%s' in table '%s'", old_name, table_name);
1729 if (mvc_check_dependency(sql, col->base.id, COLUMN_DEPENDENCY, NULL))
1730 throw(SQL, "sql.rename_column", SQLSTATE(2BM37) "ALTER TABLE: cannot rename column '%s' (there are database objects which depend on it)", old_name);
1731 if (!new_name || strcmp(new_name, str_nil) == 0 || *new_name == '\0')
1732 throw(SQL, "sql.rename_column", SQLSTATE(3F000) "ALTER TABLE: invalid new column name");
1733 if (mvc_bind_column(sql, t, new_name))
1734 throw(SQL, "sql.rename_column", SQLSTATE(3F000) "ALTER TABLE: there is a column named '%s' in table '%s'", new_name, table_name);
1735
1736 if (!sql_trans_rename_column(sql->session->tr, t, old_name, new_name))
1737 throw(SQL, "sql.rename_column",SQLSTATE(HY001) MAL_MALLOC_FAIL);
1738 return msg;
1739}
1740