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]