Changeset: 78c29ee01cdd for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=78c29ee01cdd
Added Files:
sql/backends/monet5/Tests/createorreplace.sql
sql/backends/monet5/Tests/createorreplace.stable.err
sql/backends/monet5/Tests/createorreplace.stable.out
Modified Files:
sql/backends/monet5/Tests/All
sql/server/rel_psm.c
sql/server/sql_parser.y
sql/server/sql_scan.c
Branch: default
Log Message:
Add support for CREATE OR REPLACE FUNCTION/AGGREGATE/PROCEDURE/...
diffs (truncated from 496 to 300 lines):
diff --git a/sql/backends/monet5/Tests/All b/sql/backends/monet5/Tests/All
--- a/sql/backends/monet5/Tests/All
+++ b/sql/backends/monet5/Tests/All
@@ -61,6 +61,8 @@ HAVE_LIBPY?pyloader05
HAVE_LIBPY?pyloader06
HAVE_LIBPY?pyloader07
+HAVE_LIBPY?createorreplace
+
# should this work?
#inlineUDF
diff --git a/sql/backends/monet5/Tests/createorreplace.sql
b/sql/backends/monet5/Tests/createorreplace.sql
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/Tests/createorreplace.sql
@@ -0,0 +1,55 @@
+# Test 'CREATE OR REPLACE' functionality
+
+START TRANSACTION;
+# first create the initial table and function
+CREATE TABLE createorreplacetable(i INTEGER);
+INSERT INTO createorreplacetable VALUES (2), (4), (6);
+
+# this simple function multiplies elements by 2
+CREATE FUNCTION createorreplacefunc(i INTEGER) RETURNS INTEGER LANGUAGE PYTHON
{
+ return i * 2;
+};
+
+# (4), (8), (12)
+SELECT createorreplacefunc(i) FROM createorreplacetable;
+
+COMMIT;
+
+START TRANSACTION;
+# try to create the function again: this should fail
+CREATE FUNCTION createorreplacefunc(i INTEGER) RETURNS INTEGER LANGUAGE PYTHON
{ return i * 3; };
+ROLLBACK;
+
+START TRANSACTION;
+# now replace the function with a function that multiplies elements by 3
+CREATE OR REPLACE FUNCTION createorreplacefunc(i INTEGER) RETURNS INTEGER
LANGUAGE PYTHON {
+ return i * 3;
+};
+# (6), (12), (18)
+SELECT createorreplacefunc(i) FROM createorreplacetable;
+ROLLBACK;
+
+START TRANSACTION;
+DROP FUNCTION createorreplacefunc;
+COMMIT;
+
+# aggregates
+START TRANSACTION;
+CREATE AGGREGATE createorreplaceaggregate(i INTEGER) RETURNS INTEGER LANGUAGE
PYTHON {
+ return numpy.min(i);
+};
+# (2)
+SELECT createorreplaceaggregate(i) FROM createorreplacetable;
+
+CREATE OR REPLACE AGGREGATE createorreplaceaggregate(i INTEGER) RETURNS
INTEGER LANGUAGE PYTHON {
+ return numpy.max(i);
+};
+# (6)
+SELECT createorreplaceaggregate(i) FROM createorreplacetable;
+
+ROLLBACK;
+
+
+START TRANSACTION;
+DROP TABLE createorreplacetable;
+COMMIT;
diff --git a/sql/backends/monet5/Tests/createorreplace.stable.err
b/sql/backends/monet5/Tests/createorreplace.stable.err
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/Tests/createorreplace.stable.err
@@ -0,0 +1,39 @@
+stderr of test 'createorreplace` in directory 'sql/backends/monet5` itself:
+
+
+# 14:49:51 >
+# 14:49:51 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set"
"mapi_open=true" "--set" "mapi_port=34646" "--set"
"mapi_usock=/var/tmp/mtest-26151/.s.monetdb.34646" "--set" "monet_prompt="
"--forcemito" "--dbpath=/Users/myth/opt/var/MonetDB/mTests_sql_backends_monet5"
"--set" "embedded_r=yes" "--set" "embedded_py=true"
+# 14:49:51 >
+
+# builtin opt gdk_dbpath = /Users/myth/opt/var/monetdb5/dbfarm/demo
+# builtin opt gdk_debug = 0
+# builtin opt gdk_vmtrim = no
+# builtin opt monet_prompt = >
+# builtin opt monet_daemon = no
+# builtin opt mapi_port = 50000
+# builtin opt mapi_open = false
+# builtin opt mapi_autosense = false
+# builtin opt sql_optimizer = default_pipe
+# builtin opt sql_debug = 0
+# cmdline opt gdk_nr_threads = 0
+# cmdline opt mapi_open = true
+# cmdline opt mapi_port = 34646
+# cmdline opt mapi_usock = /var/tmp/mtest-26151/.s.monetdb.34646
+# cmdline opt monet_prompt =
+# cmdline opt gdk_dbpath =
/Users/myth/opt/var/MonetDB/mTests_sql_backends_monet5
+# cmdline opt embedded_r = yes
+# cmdline opt embedded_py = true
+# cmdline opt gdk_debug = 536870922
+
+# 14:49:51 >
+# 14:49:51 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-26151" "--port=34646"
+# 14:49:51 >
+
+MAPI = (monetdb) /var/tmp/mtest-26151/.s.monetdb.34646
+QUERY = CREATE FUNCTION createorreplacefunc(i INTEGER) RETURNS INTEGER
LANGUAGE PYTHON { return i * 3; };
+ERROR = !CREATE FUNCTION: name 'createorreplacefunc' (int(32)) already in use
+
+# 14:49:52 >
+# 14:49:52 > "Done."
+# 14:49:52 >
+
diff --git a/sql/backends/monet5/Tests/createorreplace.stable.out
b/sql/backends/monet5/Tests/createorreplace.stable.out
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/Tests/createorreplace.stable.out
@@ -0,0 +1,124 @@
+stdout of test 'createorreplace` in directory 'sql/backends/monet5` itself:
+
+
+# 14:49:51 >
+# 14:49:51 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set"
"mapi_open=true" "--set" "mapi_port=34646" "--set"
"mapi_usock=/var/tmp/mtest-26151/.s.monetdb.34646" "--set" "monet_prompt="
"--forcemito" "--dbpath=/Users/myth/opt/var/MonetDB/mTests_sql_backends_monet5"
"--set" "embedded_r=yes" "--set" "embedded_py=true"
+# 14:49:51 >
+
+# MonetDB 5 server v11.26.0
+# This is an unreleased version
+# Serving database 'mTests_sql_backends_monet5', using 4 threads
+# Compiled for x86_64-apple-darwin15.6.0/64bit with 128bit integers
+# Found 8.000 GiB available main-memory.
+# Copyright (c) 1993-July 2008 CWI.
+# Copyright (c) August 2008-2016 MonetDB B.V., all rights reserved
+# Visit http://www.monetdb.org/ for further information
+# Listening for connection requests on
mapi:monetdb://dhcp-46.eduroam.cwi.nl:34646/
+# Listening for UNIX domain connection requests on
mapi:monetdb:///var/tmp/mtest-26151/.s.monetdb.34646
+# MonetDB/SQL module loaded
+# MonetDB/Python module loaded
+# MonetDB/R module loaded
+
+Ready.
+# SQL catalog created, loading sql scripts once
+# loading sql script: 09_like.sql
+# loading sql script: 10_math.sql
+# loading sql script: 11_times.sql
+# loading sql script: 12_url.sql
+# loading sql script: 13_date.sql
+# loading sql script: 14_inet.sql
+# loading sql script: 15_querylog.sql
+# loading sql script: 16_tracelog.sql
+# loading sql script: 17_temporal.sql
+# loading sql script: 18_index.sql
+# loading sql script: 20_vacuum.sql
+# loading sql script: 21_dependency_functions.sql
+# loading sql script: 22_clients.sql
+# loading sql script: 23_skyserver.sql
+# loading sql script: 25_debug.sql
+# loading sql script: 26_sysmon.sql
+# loading sql script: 27_rejects.sql
+# loading sql script: 39_analytics.sql
+# loading sql script: 39_analytics_hge.sql
+# loading sql script: 40_json.sql
+# loading sql script: 40_json_hge.sql
+# loading sql script: 41_md5sum.sql
+# loading sql script: 45_uuid.sql
+# loading sql script: 46_profiler.sql
+# loading sql script: 51_sys_schema_extension.sql
+# loading sql script: 72_fits.sql
+# loading sql script: 74_netcdf.sql
+# loading sql script: 75_storagemodel.sql
+# loading sql script: 80_statistics.sql
+# loading sql script: 80_udf.sql
+# loading sql script: 80_udf_hge.sql
+# loading sql script: 90_generator.sql
+# loading sql script: 90_generator_hge.sql
+# loading sql script: 99_system.sql
+
+# 14:49:51 >
+# 14:49:51 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-26151" "--port=34646"
+# 14:49:51 >
+
+#START TRANSACTION;
+#CREATE TABLE createorreplacetable(i INTEGER);
+#INSERT INTO createorreplacetable VALUES (2), (4), (6);
+[ 3 ]
+#CREATE FUNCTION createorreplacefunc(i INTEGER) RETURNS INTEGER LANGUAGE
PYTHON {
+# return i * 2;
+#};
+#SELECT createorreplacefunc(i) FROM createorreplacetable;
+% sys.L2 # table_name
+% L2 # name
+% int # type
+% 2 # length
+[ 4 ]
+[ 8 ]
+[ 12 ]
+#COMMIT;
+#START TRANSACTION;
+#ROLLBACK;
+#START TRANSACTION;
+#CREATE OR REPLACE FUNCTION createorreplacefunc(i INTEGER) RETURNS INTEGER
LANGUAGE PYTHON {
+# return i * 3;
+#};
+#SELECT createorreplacefunc(i) FROM createorreplacetable;
+% sys.L2 # table_name
+% L2 # name
+% int # type
+% 2 # length
+[ 6 ]
+[ 12 ]
+[ 18 ]
+#ROLLBACK;
+#START TRANSACTION;
+#DROP FUNCTION createorreplacefunc;
+#COMMIT;
+#START TRANSACTION;
+#CREATE AGGREGATE createorreplaceaggregate(i INTEGER) RETURNS INTEGER LANGUAGE
PYTHON {
+# return numpy.min(i);
+#};
+#SELECT createorreplaceaggregate(i) FROM createorreplacetable;
+% sys.L4 # table_name
+% L3 # name
+% int # type
+% 1 # length
+[ 2 ]
+#CREATE OR REPLACE AGGREGATE createorreplaceaggregate(i INTEGER) RETURNS
INTEGER LANGUAGE PYTHON {
+# return numpy.max(i);
+#};
+#SELECT createorreplaceaggregate(i) FROM createorreplacetable;
+% sys.L4 # table_name
+% L3 # name
+% int # type
+% 1 # length
+[ 6 ]
+#ROLLBACK;
+#START TRANSACTION;
+#DROP TABLE createorreplacetable;
+#COMMIT;
+
+# 14:49:52 >
+# 14:49:52 > "Done."
+# 14:49:52 >
+
diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -692,7 +692,7 @@ rel_create_function(sql_allocator *sa, c
}
static sql_rel *
-rel_create_func(mvc *sql, dlist *qname, dlist *params, symbol *res, dlist
*ext_name, dlist *body, int type, int lang)
+rel_create_func(mvc *sql, dlist *qname, dlist *params, symbol *res, dlist
*ext_name, dlist *body, int type, int lang, int replace)
{
const char *fname = qname_table(qname);
const char *sname = qname_schema(qname);
@@ -712,7 +712,9 @@ rel_create_func(mvc *sql, dlist *qname,
char is_loader = (type == F_LOADER);
char *F =
is_loader?"LOADER":(is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE"));
+ char *fn = is_loader?"loader":(is_aggr ? "aggregate" : (is_func ?
"function" : "procedure"));
char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
+ char *kf = type == F_FILT ? "filter " : type == F_UNION ? "union " : "";
assert(res || type == F_PROC || type == F_FILT || type == F_LOADER);
@@ -729,31 +731,44 @@ rel_create_func(mvc *sql, dlist *qname,
type_list = create_type_list(sql, params, 1);
if ((sf = sql_bind_func_(sql->sa, s, fname, type_list, type)) != NULL
&& create) {
- if (params) {
- char *arg_list = NULL;
- node *n;
-
- for (n = type_list->h; n; n = n->next) {
- char *tpe = subtype2string((sql_subtype *)
n->data);
+ if (replace) {
+ sql_func *func = sf->func;
+ int action = 0;
+ if (!mvc_schema_privs(sql, s)) {
+ return sql_error(sql, 02, "CREATE OR REPLACE
%s%s: access denied for %s to schema ;'%s'", KF, F, stack_get_string(sql,
"current_user"), s->base.name);
+ }
+ if (mvc_check_dependency(sql, func->base.id,
!IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY, NULL))
+ return sql_error(sql, 02, "CREATE OR REPLACE
%s%s: there are database objects dependent on %s%s %s;", KF, F, kf, fn,
func->base.name);
+
+ mvc_drop_func(sql, s, func, action);
+ } else {
+ if (params) {
+ char *arg_list = NULL;
+ node *n;
- if (arg_list) {
- char *t = arg_list;
- arg_list = sql_message("%s, %s",
arg_list, tpe);
- _DELETE(t);
- _DELETE(tpe);
- } else {
- arg_list = tpe;
+ for (n = type_list->h; n; n = n->next) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list