Changeset: 1d49a0a775ee for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/1d49a0a775ee
Modified Files:
        ChangeLog
        clients/mapiclient/mhelp.c
        sql/server/rel_psm.c
        sql/server/rel_select.c
        sql/server/rel_select.h
        sql/server/rel_semantic.c
        sql/server/rel_updates.c
        sql/server/sql_parser.y
        sql/server/sql_tokens.h
Branch: default
Log Message:

Removed support for LOADER FUNCTION.


diffs (truncated from 491 to 300 lines):

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,16 @@
 # ChangeLog file for devel
 # This file is updated with Maddlog
 
+* Mon Jun 22 2026 Sjoerd Mullender <[email protected]>
+- Removed support for LOADER FUNCTION.  Since Python UDFs are not
+  supported anymore, the loader functions can also not be supported
+  anymore.  It is no longer possible to create LOADER functions, nor is
+  it possible to use them.  Upgrading to this version will succeed if
+  such functions exist.  Use this query to find all affected functions:
+  `SELECT s.name, f.name FROM sys.functions f JOIN sys.schemas s ON s.id
+  = f.schema_id WHERE f.type = 7;`.  These functions can then be dropped
+  manually using `DROP LOADER FUNCTION ...;`.
+
 * Fri Jun 19 2026 Sjoerd Mullender <[email protected]>
 - Removed embedded Python support.  It is no longer possible to use
   user-defined functions which are written in Python (i.e. using `CREATE
diff --git a/clients/mapiclient/mhelp.c b/clients/mapiclient/mhelp.c
--- a/clients/mapiclient/mhelp.c
+++ b/clients/mapiclient/mhelp.c
@@ -141,11 +141,6 @@ SQLhelp sqlhelp1[] = {
         " [NULL [AS] string] [BEST EFFORT]\n",
         "nrofrecords,qname,column_list,headerlist,separators",
         "See also 
https://www.monetdb.org/documentation/user-guide/sql-manual/data-loading/copy-from/"},
-       {"COPY LOADER",
-        "Copy into using a user supplied parsing function",
-        "COPY LOADER INTO qname FROM qname '(' [ scalar_expression ... ] ')'",
-        "qname,scalar_expression",
-        "See also 
https://www.monetdb.org/documentation/user-guide/sql-manual/data-loading/loader-functions/"},
        {"CREATE AGGREGATE",
         "Create a user-defined aggregate function.",
         "CREATE [ OR REPLACE ] AGGREGATE [ FUNCTION ] qname '(' { '*' | [ 
param [',' ...]] } ')'\n"
@@ -224,7 +219,6 @@ SQLhelp sqlhelp1[] = {
        {"CREATE TABLE",
         "Create a new table",
         "CREATE TABLE [ IF NOT EXISTS ] qname table_source [STORAGE ident 
string]\n"
-        "CREATE TABLE [ IF NOT EXISTS ] qname FROM LOADER function_ref\n"
         "CREATE [ LOCAL | GLOBAL ] { TEMPORARY | TEMP } TABLE [ IF NOT EXISTS 
] qname table_source [on_commit]",
         "table_source,on_commit,function_ref",
         "See also 
https://www.monetdb.org/documentation/user-guide/sql-manual/data-definition/table-definition/"},
@@ -243,7 +237,6 @@ SQLhelp sqlhelp1[] = {
        {"CREATE UNLOGGED TABLE",
         "Create a new unlogged table",
         "CREATE UNLOGGED TABLE [ IF NOT EXISTS ] qname table_source [STORAGE 
ident string]\n"
-        "CREATE UNLOGGED TABLE [ IF NOT EXISTS ] qname FROM LOADER 
function_ref\n"
         "CREATE UNLOGGED TABLE [ IF NOT EXISTS ] qname table_source 
[on_commit]",
         "table_source,on_commit,function_ref",
         "See also 
https://www.monetdb.org/documentation/user-guide/sql-manual/data-definition/table-definition/"},
@@ -688,7 +681,7 @@ SQLhelp sqlhelp2[] = {
         NULL},
        {"function_type",
         NULL,
-        "{ FUNCTION | PROCEDURE | { { AGGREGATE | FILTER | LOADER | WINDOW } [ 
FUNCTION ] } }",
+        "{ FUNCTION | PROCEDURE | { { AGGREGATE | FILTER | WINDOW } [ FUNCTION 
] } }",
         NULL,
         NULL},
        {"generated_column",
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
@@ -1529,34 +1529,6 @@ drop_trigger(mvc *sql, dlist *qname, int
        return rel_drop_trigger(sql, tr->t?tr->t->s->base.name:NULL, tname, 
if_exists);
 }
 
-static sql_rel*
-create_table_from_loader(sql_query *query, dlist *qname, symbol *fcall)
-{
-       mvc *sql = query->sql;
-       sql_schema *s = cur_schema(sql);
-       char *sname = qname_schema(qname);
-       char *tname = qname_schema_object(qname);
-       sql_subfunc *loader = NULL;
-       sql_rel *rel = NULL;
-       sql_table *t = NULL;
-
-       if (sname && !(s = mvc_bind_schema(sql, sname)))
-               return sql_error(sql, ERR_NOTFOUND, SQLSTATE(3F000) "CREATE 
TABLE FROM LOADER: no such schema '%s'", sname);
-       if ((t = mvc_bind_table(sql, s, tname)))
-               return sql_error(sql, 02, SQLSTATE(42S01) "CREATE TABLE FROM 
LOADER: name '%s' already in use", tname);
-       if (!mvc_schema_privs(sql, s))
-               return sql_error(sql, 02, SQLSTATE(42000) "CREATE TABLE FROM 
LOADER: insufficient privileges for user '%s' in schema '%s'", 
get_string_global_var(sql, "current_user"), s->base.name);
-
-       rel = rel_loader_function(query, fcall, new_exp_list(sql->sa), &loader);
-       if (!rel || !loader)
-               return NULL;
-
-       loader->sname = s ? ma_strdup(sql->sa, s->base.name) : NULL;
-       loader->tname = tname ? ma_strdup(sql->sa, tname) : NULL;
-
-       return rel;
-}
-
 static list *
 rel_paramlist( sql_query *query, symbol *nop)
 {
@@ -1637,18 +1609,6 @@ rel_psm(sql_query *query, symbol *s)
                } else
                        ret = rel_psm_stmt(sql->sa, rel_psm_call(query, 
s->data.sym));
                break;
-       case SQL_CREATE_TABLE_LOADER:
-       {
-               dlist *l = s->data.lval;
-               dlist *qname = l->h->data.lval;
-               symbol *sym = l->h->next->data.sym;
-
-               ret = create_table_from_loader(query, qname, sym);
-               if (ret == NULL)
-                       return NULL;
-               ret = rel_psm_stmt(sql->sa, exp_rel(sql, ret));
-               sql->type = Q_SCHEMA;
-       }       break;
        case SQL_CREATE_TRIGGER:
        {
                dlist *l = s->data.lval;
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -6588,81 +6588,3 @@ schema_selects(sql_query *query, sql_sch
        sql->session->schema = os;
        return res;
 }
-
-sql_rel *
-rel_loader_function(sql_query *query, symbol* fcall, list *fexps, sql_subfunc 
**loader_function)
-{
-       mvc *sql = query->sql;
-       sql_rel *sq = NULL;
-       dnode *l = fcall->data.lval->h;
-       char *sname = qname_schema(l->data.lval);
-       char *fname = qname_schema_object(l->data.lval);
-
-       list *tl = sa_list(sql->sa);
-       list *exps = sa_list(sql->sa);
-       if (l->next)
-               l = l->next; /* skip distinct */
-       if (l->next) { /* table call with subquery */
-               if (l->next->type == type_symbol || l->next->type == type_list) 
{
-                       int count = 0;
-                       symbol *subquery = NULL;
-                       dnode *n = NULL;
-
-                       if (l->next->type == type_symbol)
-                               n = l->next;
-                       else
-                               n = 
l->next->data.lval?l->next->data.lval->h:NULL;
-
-                       for (dnode *m = n; m; m = m->next) {
-                               if (m->type == type_symbol && 
m->data.sym->token == SQL_SELECT)
-                                       subquery = m->data.sym;
-                               count++;
-                       }
-                       if (subquery && count > 1)
-                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: The input for the loader function '%s' must be either a single sub 
query, or a list of values", fname);
-
-                       if (subquery) {
-                               exp_kind ek = { type_value, card_relation, TRUE 
};
-                               if (!(sq = rel_subquery(query, subquery, ek)))
-                                       return NULL;
-                       } else {
-                               exp_kind ek = { type_value, card_column, TRUE };
-                               list *exps = sa_list(sql->sa);
-                               for ( ; n; n = n->next) {
-                                       sql_exp *e = rel_value_exp(query, NULL, 
n->data.sym, sql_sel | sql_from, ek);
-
-                                       if (!e)
-                                               return NULL;
-                                       append(exps, e);
-                               }
-                               sq = rel_project(sql->sa, NULL, exps);
-                       }
-               }
-               if (!sq)
-                       return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) 
"SELECT: no such loader function %s%s%s'%s'", sname ? "'":"", sname ? sname : 
"", sname ? "'.":"", fname);
-               for (node *en = sq->exps->h; en; en = en->next) {
-                       sql_exp *e = en->data;
-
-                       append(exps, e = exp_ref(sql, e));
-                       append(tl, exp_subtype(e));
-               }
-       }
-
-       sql_exp *e = NULL;
-       if (!(e = find_table_function(sql, sname, fname, exps, tl, F_LOADER)))
-               return NULL;
-       sql_subfunc *sf = e->f;
-       if (sq) {
-               for (node *n = sq->exps->h, *m = sf->func->ops->h ; n && m ; n 
= n->next, m = m->next) {
-                       sql_exp *e = (sql_exp*) n->data;
-                       sql_arg *a = (sql_arg*) m->data;
-                       if (!exp_subtype(e) && rel_set_type_param(sql, 
&(a->type), sq, e, 0) < 0)
-                               return NULL;
-               }
-       }
-
-       if (loader_function)
-               *loader_function = sf;
-
-       return rel_table_func(sql->sa, sq, e, fexps, 
(sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
-}
diff --git a/sql/server/rel_select.h b/sql/server/rel_select.h
--- a/sql/server/rel_select.h
+++ b/sql/server/rel_select.h
@@ -31,7 +31,6 @@ extern sql_exp *rel_nop_(mvc *sql, sql_r
 extern sql_rel *rel_with_query(sql_query *query, symbol *q);
 extern sql_rel *table_ref(sql_query *query, symbol *tableref, int lateral, 
list *refs);
 extern sql_exp *find_table_function(mvc *sql, char *sname, char *fname, list 
*exps, list *tl, sql_ftype type);
-extern sql_rel *rel_loader_function(sql_query* query, symbol* s, list *fexps, 
sql_subfunc **loader_function);
 extern list *check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, 
list *exps, sql_subfunc *sf, int maybe_zero_or_one, bool internal /*or second 
compile */);
 extern sql_rel *rel_reduce_on_column_privileges(mvc *sql, sql_rel *rel, 
sql_table *t);
 
diff --git a/sql/server/rel_semantic.c b/sql/server/rel_semantic.c
--- a/sql/server/rel_semantic.c
+++ b/sql/server/rel_semantic.c
@@ -169,8 +169,6 @@ rel_semantic(sql_query *query, symbol *s
        case SQL_CALL:
        case SQL_SET:
 
-       case SQL_CREATE_TABLE_LOADER:
-
        case SQL_CREATE_TRIGGER:
        case SQL_DROP_TRIGGER:
 
@@ -186,7 +184,6 @@ rel_semantic(sql_query *query, symbol *s
        case SQL_COPYINTO:
        case SQL_BINCOPYFROM:
        case SQL_BINCOPYINTO:
-       case SQL_COPYLOADER:
                return rel_updates(query, s);
 
        case SQL_WITH:
diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -1548,20 +1548,6 @@ table_column_types(allocator *sa, sql_ta
        return types;
 }
 
-static list *
-table_column_names_and_defaults(allocator *sa, sql_table *t)
-{
-       node *n;
-       list *types = sa_list(sa);
-
-       if (ol_first_node(t->columns)) for (n = ol_first_node(t->columns); n; n 
= n->next) {
-               sql_column *c = n->data;
-               append(types, &c->base.name);
-               append(types, c->def);
-       }
-       return types;
-}
-
 static sql_rel *
 rel_import(mvc *sql, sql_table *t, const char *tsep, const char *rsep, const 
char *ssep, const char *ns, const char *filename, lng nr, lng offset, int 
best_effort, dlist *fwf_widths, int onclient, int escape, const char* decsep, 
const char *decskip)
 {
@@ -1937,47 +1923,6 @@ bincopyfrom(sql_query *query, dlist *qna
 }
 
 static sql_rel *
-copyfromloader(sql_query *query, dlist *qname, symbol *fcall)
-{
-       mvc *sql = query->sql;
-       char *sname = qname_schema(qname);
-       char *tname = qname_schema_object(qname);
-       sql_subfunc *loader = NULL;
-       sql_rel *rel = NULL;
-       sql_table *t;
-       list *mts;
-
-       if (!copy_allowed(sql, 1))
-               return sql_error(sql, 02, SQLSTATE(42000) "COPY LOADER INTO: 
insufficient privileges: "
-                               "COPY LOADER INTO requires database 
administrator rights");
-       t = find_table_or_view_on_scope(sql, NULL, sname, tname, "COPY INTO", 
false);
-       //TODO the COPY LOADER INTO should return an insert relation (instead 
of ddl) to handle partitioned tables properly
-       if (insert_allowed(sql, t, tname, "COPY LOADER INTO", "copy loader 
into") == NULL)
-               return NULL;
-       if (isPartitionedByColumnTable(t) || isPartitionedByExpressionTable(t))
-               return sql_error(sql, 02, SQLSTATE(42000) "COPY LOADER INTO: 
not possible for partitioned tables at the moment");
-       if ((mts = partition_find_mergetables(sql, t))) {
-               for (node *n = mts->h ; n ; n = n->next) {
-                       sql_part *pt = n->data;
-
-                       if ((isPartitionedByColumnTable(pt->t) || 
isPartitionedByExpressionTable(pt->t)))
-                               return sql_error(sql, 02, SQLSTATE(42000) "COPY 
LOADER INTO: not possible for tables child of partitioned tables at the 
moment");
-               }
-       }
-
-       rel = rel_loader_function(query, fcall, new_exp_list(sql->sa), &loader);
-       if (!rel || !loader)
-               return NULL;
-
-       loader->sname = t->s ? ma_strdup(sql->sa, t->s->base.name) : NULL;
-       loader->tname = tname ? ma_strdup(sql->sa, tname) : NULL;
-       loader->coltypes = table_column_types(sql->sa, t);
-       loader->colnames = table_column_names_and_defaults(sql->sa, t);
-
-       return rel;
-}
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to