Changeset: c14ea353b4cd for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c14ea353b4cd
Modified Files:
sql/backends/monet5/sql.c
sql/server/rel_updates.c
sql/server/sql_parser.y
Branch: default
Log Message:
Update COPY BINARY INTO to accept a column list (like COPY FROM).
This is accomplished by passing str:nil instead of a filename for columns that
are not mentioned. Missing columns are then filled with NULL values.
diffs (202 lines):
diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -3635,6 +3635,7 @@ mvc_bin_import_table_wrap(Client cntxt,
mvc *m = NULL;
str msg;
BUN cnt = 0;
+ int init = 0;
int i;
str sname = *getArgReference_str(stk, pci, 0 + pci->retc);
str tname = *getArgReference_str(stk, pci, 1 + pci->retc);
@@ -3661,9 +3662,15 @@ mvc_bin_import_table_wrap(Client cntxt,
for (i = pci->retc + 2, n = t->columns.set->h; i < pci->argc && n; i++,
n = n->next) {
sql_column *col = n->data;
const char *fname = *getArgReference_str(stk, pci, i);
- size_t flen = strlen(fname);
+ size_t flen;
char *fn;
+ if (strcmp(fname, str_nil) == 0) {
+ // no file name passed for this column
+ continue;
+ }
+ flen = strlen(fname);
+
if (ATOMvarsized(col->type.type->localtype) &&
col->type.type->localtype != TYPE_str)
throw(SQL, "sql", "Failed to attach file %s",
*getArgReference_str(stk, pci, i));
fn = GDKmalloc(flen + 1);
@@ -3684,12 +3691,16 @@ mvc_bin_import_table_wrap(Client cntxt,
sql_column *col = n->data;
BAT *c = NULL;
int tpe = col->type.type->localtype;
+ str fname = *getArgReference_str(stk, pci, i);
/* handle the various cases */
- if (tpe < TYPE_str || tpe == TYPE_date || tpe == TYPE_daytime
|| tpe == TYPE_timestamp) {
- c = BATattach(col->type.type->localtype,
*getArgReference_str(stk, pci, i), PERSISTENT);
+ if (strcmp(fname, str_nil) == 0) {
+ // no filename for this column, skip for now because we
potentially don't know the count yet
+ continue;
+ } else if (tpe < TYPE_str || tpe == TYPE_date || tpe ==
TYPE_daytime || tpe == TYPE_timestamp) {
+ c = BATattach(col->type.type->localtype, fname,
PERSISTENT);
if (c == NULL)
- throw(SQL, "sql", "Failed to attach file %s",
*getArgReference_str(stk, pci, i));
+ throw(SQL, "sql", "Failed to attach file %s",
fname);
BATsetaccess(c, BAT_READ);
} else if (tpe == TYPE_str) {
/* get the BAT and fill it with the strings */
@@ -3699,7 +3710,7 @@ mvc_bin_import_table_wrap(Client cntxt,
/* this code should be extended to deal with larger
text strings. */
f = fopen(*getArgReference_str(stk, pci, i), "r");
if (f == NULL)
- throw(SQL, "sql", "Failed to re-open file %s",
*getArgReference_str(stk, pci, i));
+ throw(SQL, "sql", "Failed to re-open file %s",
fname);
buf = GDKmalloc(bufsiz);
if (!buf) {
@@ -3715,14 +3726,35 @@ mvc_bin_import_table_wrap(Client cntxt,
fclose(f);
GDKfree(buf);
} else {
- throw(SQL, "sql", "Failed to attach file %s",
*getArgReference_str(stk, pci, i));
+ throw(SQL, "sql", "Failed to attach file %s", fname);
}
- if (i != (pci->retc + 2) && cnt != BATcount(c))
+ if (init && cnt != BATcount(c))
throw(SQL, "sql", "binary files for table '%s' have
inconsistent counts", tname);
cnt = BATcount(c);
+ init = 1;
*getArgReference_bat(stk, pci, i - (2 + pci->retc)) =
c->batCacheid;
BBPkeepref(c->batCacheid);
}
+ if (init) {
+ for (i = pci->retc + 2, n = t->columns.set->h; i < pci->argc &&
n; i++, n = n->next) {
+ // now that we know the BAT count, we can fill in the
columns for which no parameters were pasesd
+ sql_column *col = n->data;
+ BAT *c = NULL;
+ int tpe = col->type.type->localtype;
+
+ str fname = *getArgReference_str(stk, pci, i);
+ if (strcmp(fname, str_nil) == 0) {
+ BUN loop = 0;
+ const void* nil = ATOMnilptr(tpe);
+ c = COLnew(0, tpe, cnt, PERSISTENT);
+ for(loop = 0; loop < cnt; loop++) {
+ BUNappend(c, nil, 0);
+ }
+ *getArgReference_bat(stk, pci, i - (2 +
pci->retc)) = c->batCacheid;
+ BBPkeepref(c->batCacheid);
+ }
+ }
+ }
return MAL_SUCCEED;
}
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
@@ -1415,7 +1415,7 @@ copyfrom(mvc *sql, dlist *qname, dlist *
}
static sql_rel *
-bincopyfrom(mvc *sql, dlist *qname, dlist *files, int constraint)
+bincopyfrom(mvc *sql, dlist *qname, dlist *columns, dlist *files, int
constraint)
{
char *sname = qname_schema(qname);
char *tname = qname_table(qname);
@@ -1426,11 +1426,14 @@ bincopyfrom(mvc *sql, dlist *qname, dlis
node *n;
sql_rel *res;
list *exps, *args;
- sql_subtype tpe;
+ sql_subtype strtpe;
sql_exp *import;
sql_schema *sys = mvc_bind_schema(sql, "sys");
sql_subfunc *f = sql_find_func(sql->sa, sys, "copyfrom", 2, F_UNION,
NULL);
+ list *collist;
+ size_t i;
+ assert(f);
if (!copy_allowed(sql, 1)) {
(void) sql_error(sql, 02, "COPY INTO: insufficient privileges: "
"binary COPY INTO requires database
administrator rights");
@@ -1455,18 +1458,37 @@ bincopyfrom(mvc *sql, dlist *qname, dlis
if (files == NULL)
return sql_error(sql, 02, "COPY INTO: must specify files");
+ collist = check_table_columns(sql, t, columns, "COPY BINARY", tname);
+ if (!collist)
+ return NULL;
+
f->res = table_column_types(sql->sa, t);
- sql_find_subtype(&tpe, "varchar", 0, 0);
- args = append( append( new_exp_list(sql->sa),
- exp_atom_str(sql->sa, t->s?t->s->base.name:NULL, &tpe)),
- exp_atom_str(sql->sa, t->base.name, &tpe));
+ sql_find_subtype(&strtpe, "varchar", 0, 0);
+ args = append( append( new_exp_list(sql->sa),
+ exp_atom_str(sql->sa, t->s?t->s->base.name:NULL, &strtpe)),
+ exp_atom_str(sql->sa, t->base.name, &strtpe));
- for (dn = files->h; dn; dn = dn->next) {
- append(args, exp_atom_str(sql->sa, dn->data.sval, &tpe));
+ // create the list of files that is passed to the function as parameter
+ for(i = 0; i < t->columns.set->cnt; i++) {
+ // we have one file per column, however, because we have column
selection that file might be NULL
+ // first, check if this column number is present in the passed
in the parameters
+ int found = 0;
+ dn = files->h;
+ for (n = collist->h; n && dn; n = n->next, dn = dn->next) {
+ sql_column *c = n->data;
+ if (i == c->colnr) {
+ // this column number was present in the input
arguments; pass in the file name
+ append(args, exp_atom_str(sql->sa,
dn->data.sval, &strtpe));
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ // this column was not present in the input arguments;
pass in NULL
+ append(args, exp_atom_str(sql->sa, NULL, &strtpe));
+ }
+ }
- /* extend the bincopyfrom, with extra args and types */
- }
-
import = exp_op(sql->sa, args, f);
exps = new_exp_list(sql->sa);
@@ -1696,7 +1718,7 @@ rel_updates(mvc *sql, symbol *s)
{
dlist *l = s->data.lval;
- ret = bincopyfrom(sql, l->h->data.lval, l->h->next->data.lval,
l->h->next->next->data.i_val);
+ ret = bincopyfrom(sql, l->h->data.lval, l->h->next->data.lval,
l->h->next->next->data.lval, l->h->next->next->next->data.i_val);
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
@@ -2567,15 +2567,16 @@ copyfrom_stmt:
append_list(l, $4);
append_symbol(l, $6);
$$ = _symbol_create_list( SQL_COPYLOADER, l ); }
- | COPY opt_nr BINARY INTO qname FROM string_commalist /* binary copy from
*/ opt_constraint
+ | COPY opt_nr BINARY INTO qname opt_column_list FROM string_commalist /*
binary copy from */ opt_constraint
{ dlist *l = L();
if ($2 != NULL) {
yyerror(m, "COPY INTO: cannot pass number of records when using
binary COPY INTO");
YYABORT;
}
append_list(l, $5);
- append_list(l, $7);
- append_int(l, $8);
+ append_list(l, $6);
+ append_list(l, $8);
+ append_int(l, $9);
$$ = _symbol_create_list( SQL_BINCOPYFROM, l ); }
| COPY query_expression_def INTO string opt_seps opt_null_string
{ dlist *l = L();
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list