Changeset: d438d67ff2c5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d438d67ff2c5
Modified Files:
        sql/server/rel_updates.c
        sql/server/sql_parser.y
        sql/server/sql_symbol.c
        sql/server/sql_symbol.h
Branch: default
Log Message:

Introduce CopyFromNode to streamline COPY INTO handling


diffs (truncated from 310 to 300 lines):

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
@@ -1705,26 +1705,22 @@ valid_decsep(const char *s)
 }
 
 static sql_rel *
-copyfrom(sql_query *query, dlist *qname, dlist *columns, dlist *files, dlist 
*headers, dlist *seps, dlist *nr_offset, str null_string, int best_effort, 
dlist *fwf_widths, int onclient, int escape, dlist *decimal_seps)
+copyfrom(sql_query *query, CopyFromNode *copy)
 {
        mvc *sql = query->sql;
        sql_rel *rel = NULL;
-       char *sname = qname_schema(qname);
-       char *tname = qname_schema_object(qname);
+       char *sname = qname_schema(copy->qname);
+       char *tname = qname_schema_object(copy->qname);
        sql_table *t = NULL, *nt = NULL;
-       const char *tsep = seps->h->data.sval;
-       char *rsep = seps->h->next->data.sval; /* not const, might need 
adjusting */
-       const char *ssep = 
(seps->h->next->next)?seps->h->next->next->data.sval:NULL;
-       const char *ns = (null_string)?null_string:"null";
-       lng nr = (nr_offset)?nr_offset->h->data.l_val:-1;
-       lng offset = (nr_offset)?nr_offset->h->next->data.l_val:0;
+       const char *tsep = copy->tsep;
+       char *rsep = copy->rsep; /* not const, might need adjusting */
+       const char *ssep = copy->ssep;
+       const char *ns = copy->null_string ? copy->null_string : "null";
+       lng nr = copy->nrows;
+       lng offset = copy->offset;
        list *collist;
        int reorder = 0;
-       const char *decsep = decimal_seps->h->data.sval;
-       const char *decskip = decimal_seps->h->next ? 
decimal_seps->h->next->data.sval: NULL;
-
-       assert(!nr_offset || nr_offset->h->type == type_lng);
-       assert(!nr_offset || nr_offset->h->next->type == type_lng);
+       dlist *headers = copy->header_list;
 
        if (strcmp(rsep, "\r\n") == 0) {
                /* silently fix it */
@@ -1736,18 +1732,18 @@ copyfrom(sql_query *query, dlist *qname,
                                "that will never match, use '\\n' instead");
        }
 
-       if (!valid_decsep(decsep))
+       if (!valid_decsep(copy->decsep))
                return sql_error(sql, 02, SQLSTATE(42000) "COPY INTO: invalid 
decimal separator");
-       if (decskip && !valid_decsep(decskip))
+       if (copy->decskip && !valid_decsep(copy->decskip))
                return sql_error(sql, 02, SQLSTATE(42000) "COPY INTO: invalid 
thousands separator");
-       if (decskip && strcmp(decsep, decskip) == 0)
+       if (copy->decskip && strcmp(copy->decsep, copy->decskip) == 0)
                return sql_error(sql, 02, SQLSTATE(42000) "COPY INTO: decimal 
separator and thousands separator must be different");
 
        t = find_table_or_view_on_scope(sql, NULL, sname, tname, "COPY INTO", 
false);
        if (insert_allowed(sql, t, tname, "COPY INTO", "copy into") == NULL)
                return NULL;
 
-       collist = check_table_columns(sql, t, columns, "COPY INTO", tname);
+       collist = check_table_columns(sql, t, copy->column_list, "COPY INTO", 
tname);
        if (!collist)
                return NULL;
        /* If we have a header specification use intermediate table, for
@@ -1807,10 +1803,10 @@ copyfrom(sql_query *query, dlist *qname,
                        headers = NULL;
                reorder = 1;
        }
-       if (files) {
-               dnode *n = files->h;
+       if (copy->sources) {
+               dnode *n = copy->sources->h;
 
-               if (!onclient && !copy_allowed(sql, 1)) {
+               if (!copy->on_client && !copy_allowed(sql, 1)) {
                        return sql_error(sql, 02, SQLSTATE(42000)
                                         "COPY INTO: insufficient privileges: "
                                         "COPY INTO from file(s) requires 
database administrator rights, "
@@ -1821,7 +1817,7 @@ copyfrom(sql_query *query, dlist *qname,
                        const char *fname = n->data.sval;
                        sql_rel *nrel;
 
-                       if (!onclient && fname && !MT_path_absolute(fname)) {
+                       if (!copy->on_client && fname && 
!MT_path_absolute(fname)) {
                                char *fn = ATOMformat(TYPE_str, fname);
                                sql_error(sql, 02, SQLSTATE(42000) "COPY INTO: 
filename must "
                                          "have absolute path: %s", fn);
@@ -1829,7 +1825,7 @@ copyfrom(sql_query *query, dlist *qname,
                                return NULL;
                        }
 
-                       nrel = rel_import(sql, nt, tsep, rsep, ssep, ns, fname, 
nr, offset, best_effort, fwf_widths, onclient, escape, decsep, decskip);
+                       nrel = rel_import(sql, nt, tsep, rsep, ssep, ns, fname, 
nr, offset, copy->best_effort, copy->fwf_widths, copy->on_client, copy->escape, 
copy->decsep, copy->decskip);
 
                        if (!rel)
                                rel = nrel;
@@ -1843,8 +1839,8 @@ copyfrom(sql_query *query, dlist *qname,
                                return rel;
                }
        } else {
-               assert(onclient == 0);
-               rel = rel_import(sql, nt, tsep, rsep, ssep, ns, NULL, nr, 
offset, best_effort, NULL, onclient, escape, decsep, decskip);
+               assert(copy->on_client == 0);
+               rel = rel_import(sql, nt, tsep, rsep, ssep, ns, NULL, nr, 
offset, copy->best_effort, NULL, copy->on_client, copy->escape, copy->decsep, 
copy->decskip);
        }
        if (headers) {
                dnode *n;
@@ -2239,21 +2235,8 @@ rel_updates(sql_query *query, symbol *s)
        switch (s->token) {
        case SQL_COPYFROM:
        {
-               dlist *l = s->data.lval;
-
-               ret = copyfrom(query,
-                               l->h->data.lval,
-                               l->h->next->data.lval,
-                               l->h->next->next->data.lval,
-                               l->h->next->next->next->data.lval,
-                               l->h->next->next->next->next->data.lval,
-                               l->h->next->next->next->next->next->data.lval,
-                               
l->h->next->next->next->next->next->next->data.sval,
-                               
l->h->next->next->next->next->next->next->next->data.i_val,
-                               
l->h->next->next->next->next->next->next->next->next->data.lval,
-                               
l->h->next->next->next->next->next->next->next->next->next->data.i_val,
-                               
l->h->next->next->next->next->next->next->next->next->next->next->data.i_val,
-                               
l->h->next->next->next->next->next->next->next->next->next->next->next->data.lval);
+               CopyFromNode *copy = (CopyFromNode*)s;
+               ret = copyfrom(query, copy);
                sql->type = Q_UPDATE;
        }
                break;
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -203,6 +203,7 @@ int yydebug=1;
        check_search_condition
        comment_on_statement
        control_statement
+       copyload_stmt
        copyfrom_stmt
        copyto_stmt
        create_statement
@@ -2961,7 +2962,7 @@ update_statement:
  | insert_stmt
  | update_stmt
  | merge_stmt
- | copyfrom_stmt
+ | copyload_stmt
  | copyto_stmt
  ;
 
@@ -3048,38 +3049,47 @@ opt_on_location:
 copyfrom_stmt:
 /*  1    2      3    4     5               6    7                8             
  9               10       11               12         13              14       
       15 */
     COPY opt_nr INTO qname opt_column_list FROM string_commalist 
opt_header_list opt_on_location opt_seps opt_decimal_seps opt_escape 
opt_null_string opt_best_effort opt_fwf_widths
-       { dlist *l = L();
-         append_list(l, $4);
-         append_list(l, $5);
-         append_list(l, $7);
-         append_list(l, $8);
-         append_list(l, $10);
-         append_list(l, $2);
-         append_string(l, $13);
-         append_int(l, $14);
-         append_list(l, $15);
-         append_int(l, $9);
-         append_int(l, $12);
-         append_list(l, $11);
-         $$ = _symbol_create_list( SQL_COPYFROM, l ); }
+       { CopyFromNode *copy = newCopyFromNode(SA,
+               /* qname */ $4,
+               /* column_list */ $5,
+               /* sources */ $7,
+               /* header_list */ $8,
+               /* nr_offset */ $2);
+         copy->tsep = $10->h->data.sval;
+         copy->rsep = $10->h->next->data.sval;
+         copy->ssep = $10->cnt > 2 ? $10->h->next->next->data.sval : NULL;
+         copy->null_string = $13,
+         copy->best_effort = !!$14;
+         copy->fwf_widths = $15;
+         copy->on_client = !!$9;
+         copy->escape = !!$12;
+         copy->decsep = $11->h->data.sval;
+         copy->decskip = $11->cnt > 1 ? $11->h->next->data.sval : NULL;
+         $$ = (symbol*)copy; }
 /*  1    2      3    4     5               6    7      8               9       
 10               11         12              13*/
   | COPY opt_nr INTO qname opt_column_list FROM STDIN  opt_header_list 
opt_seps opt_decimal_seps opt_escape opt_null_string opt_best_effort
-       { dlist *l = L();
-         append_list(l, $4);
-         append_list(l, $5);
-         append_list(l, NULL);
-         append_list(l, $8);
-         append_list(l, $9);
-         append_list(l, $2);
-         append_string(l, $12);
-         append_int(l, $13);
-         append_list(l, NULL);
-         append_int(l, 0);
-         append_int(l, $11);
-         append_list(l, $10);
-         $$ = _symbol_create_list( SQL_COPYFROM, l ); }
-/*  1    2         3    4     5    6 */
-  | COPY sqlLOADER INTO qname FROM func_ref
+       { CopyFromNode *copy = newCopyFromNode(SA,
+               /* qname */ $4,
+               /* column_list */ $5,
+               /* sources */ NULL,
+               /* header_list */ $8,
+               /* nrows */ $2);
+         copy->tsep = $9->h->data.sval;
+         copy->rsep = $9->h->next->data.sval;
+         copy->ssep = $9->cnt > 2 ? $9->h->next->next->data.sval : NULL;
+         copy->null_string = $12,
+         copy->best_effort = !!$13;
+         copy->fwf_widths = NULL;
+         copy->on_client = false;
+         copy->escape = !!$11;
+         copy->decsep = $10->h->data.sval;
+         copy->decskip = $10->cnt > 1 ? $10->h->next->data.sval : NULL;
+         $$ = (symbol*)copy; }
+
+copyload_stmt:
+   copyfrom_stmt { $$ = $1; }
+/*   1    2         3    4     5    6 */
+   | COPY sqlLOADER INTO qname FROM func_ref
        { dlist *l = L();
          append_list(l, $4);
          append_symbol(l, $6);
diff --git a/sql/server/sql_symbol.c b/sql/server/sql_symbol.c
--- a/sql/server/sql_symbol.c
+++ b/sql/server/sql_symbol.c
@@ -284,6 +284,38 @@ newSelectNode(allocator *sa, int distinc
        return s;
 }
 
+CopyFromNode *
+newCopyFromNode(allocator *sa, struct dlist *qname, struct dlist *column_list, 
struct dlist *sources, struct dlist *header_list, struct dlist *nr_offset)
+{
+       CopyFromNode *n = SA_NEW(sa, CopyFromNode);
+       if (n) {
+               *n = (CopyFromNode) {
+                       qname: qname,
+                       column_list: column_list,
+                       sources: sources,
+                       header_list: header_list,
+                       nrows: -1,
+                       offset: 0,
+                       tsep: "|",
+                       rsep: "\n",
+                       ssep: NULL,
+                       null_string: NULL,
+                       best_effort: false,
+                       fwf_widths: NULL,
+                       on_client: false,
+                       escape: true,
+                       decsep: ".",
+                       decskip: NULL,
+               };
+               symbol_init(&n->s, SQL_COPYFROM, type_symbol);
+               if (nr_offset) {
+                       n->nrows = nr_offset->h->data.l_val;
+                       n->offset = nr_offset->h->next->data.l_val;
+               }
+       }
+       return n;
+}
+
 symbol *
 newAtomNode(allocator *sa, atom *data)
 {
diff --git a/sql/server/sql_symbol.h b/sql/server/sql_symbol.h
--- a/sql/server/sql_symbol.h
+++ b/sql/server/sql_symbol.h
@@ -90,6 +90,27 @@ typedef struct AtomNode {
        struct atom *a;
 } AtomNode;
 
+typedef struct CopyFromNode {
+       symbol s;
+
+       struct dlist *qname; /* never empty */
+       struct dlist *column_list; /* never empty */
+       struct dlist *sources; /* or NULL for FROM STDIN */
+       struct dlist *header_list; /* or NULL */
+       lng nrows; /* default -1, meaning not set */
+       lng offset; /* default 0 */
+       char *tsep; /* column separator, default "|" */
+       char *rsep; /* row separator, default "\n" */
+       char *ssep; /* quote character, default NULL */
+       char *null_string; /* default NULL, not "NULL"! */
+       bool best_effort; /* default false */
+       struct dlist *fwf_widths; /* must be NULL for FROM STDIN */
+       bool on_client; /* must be false for FROM STDIN */
+       bool escape; /* default true */
+       char *decsep; /* default "." */
+       char *decskip; /* default NULL */
+} CopyFromNode;
+
 extern symbol *symbol_create(allocator *sa, tokens token, char *data);
 extern symbol *symbol_create_list(allocator *sa, tokens token, dlist *data);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to