Changeset: eb9a9582ba77 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=eb9a9582ba77
Modified Files:
        sql/backends/monet5/sql.c
        sql/common/sql_types.c
        sql/server/rel_updates.c
        sql/server/sql_parser.y
        sql/server/sql_scan.c
Branch: fixed-width-format
Log Message:

COPY INTO table FWF (1,2,3); now works


diffs (267 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
@@ -3410,10 +3410,16 @@ mvc_import_table_wrap(Client cntxt, MalB
        lng *offset = getArgReference_lng(stk, pci, pci->retc + 7);
        int *locked = getArgReference_int(stk, pci, pci->retc + 8);
        int *besteffort = getArgReference_int(stk, pci, pci->retc + 9);
+       char *fixed_widths = NULL;
        str msg = MAL_SUCCEED;
        bstream *s = NULL;
        stream *ss;
 
+       if (pci->argc - pci->retc > 10) {
+               fixed_widths = *getArgReference_str(stk, pci, pci->retc + 10);
+
+       }
+
        (void) mb;              /* NOT USED */
        if ((msg = checkSQLContext(cntxt)) != NULL)
                return msg;
@@ -3483,14 +3489,29 @@ mvc_import_table_wrap(Client cntxt, MalB
                        return msg;
                }
                GDKfree(fn);
-
-               // FIXME
-               if (GDKgetenv_isyes("testfwf")) {
-                       fprintf(stderr, "### FWF IMPORT ON %s ###\n", *fname);
-                       size_t *widths = malloc(sizeof(size_t)*400);
-                       size_t i = 0;
-                       widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 9;  
widths[i++] = 12;  widths[i++] = 8;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 8;  
widths[i++] = 8;  widths[i++] = 30;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 9;  widths[i++] = 4;  widths[i++] = 4;  widths[i++] = 2;  
widths[i++] = 8;  widths[i++] = 9;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 9;  widths[i++] = 9;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 9;  widths[i++] = 9;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 9;  widths[i++] = 9;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 9;  widths[i++] = 9;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 9;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 4;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  wi
 dths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 3;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 4;  
widths[i++] = 2;  widths[i++] = 8;  widths[i++] = 2;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i+
 +] = 2;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 
3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 9;  widths[i++] = 9;  
widths[i++] = 9;  widths[i++] = 8;  widths[i++] = 8;  widths[i++] = 8;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 9;  widths[i++] = 9;  widths[i++] = 9;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 9;  widths[i++] = 9;  widths[i++] = 9;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;
   widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 9;  widths[i++] = 9;  
widths[i++] = 9;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 9;  widths[i++] = 9;  width
 s[i++] = 9;  widths[i++] = 4;  widths[i++] = 4;  widths[i++] = 4;  widths[i++] 
= 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] 
 = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  w
 idths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 12;  widths[i++] = 12;  widths[i++] = 12;  widths[i++] = 8;  
widths[i++] = 8;  widths[i++] = 8;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  widths[i++] = 3;  
widths[i++] = 3;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  
widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 2;  widths[i++] = 40;
-                       ss = stream_fwf_create(ss, 376, widths, ' ');
+               if (fixed_widths) {
+                       size_t ncol = 0, current_width_entry = 0, i;
+                       size_t *widths;
+                       char* val_start = fixed_widths;
+                       size_t width_len = strlen(fixed_widths);
+                       for (i = 0; i < width_len; i++) {
+                               if (fixed_widths[i] == '|') {
+                                       ncol++;
+                               }
+                       }
+                       widths = malloc(sizeof(size_t) * ncol);
+                       if (!widths) {
+                               // TODO: free other stuff
+                               throw(MAL, "sql.copy_from", MAL_MALLOC_FAIL);
+                       }
+                       for (i = 0; i < width_len; i++) {
+                               if (fixed_widths[i] == '|') {
+                                       fixed_widths[i] = '\0';
+                                       widths[current_width_entry++] = 
(size_t) atoll(val_start);
+                                       val_start = fixed_widths + i + 1;
+                               }
+                       }
+                       ss = stream_fwf_create(ss, ncol, widths, ' ');
                }
 #if SIZEOF_VOID_P == 4
                s = bstream_create(ss, 0x20000);
diff --git a/sql/common/sql_types.c b/sql/common/sql_types.c
--- a/sql/common/sql_types.c
+++ b/sql/common/sql_types.c
@@ -1760,9 +1760,9 @@ sqltypeinit( sql_allocator *sa)
                                sres, FALSE, F_FUNC, SCALE_FIX);
        }
        sres = create_arg(sa, NULL, sql_create_subtype(sa, TABLE, 0, 0), 
ARG_OUT); 
-       /* copyfrom fname (arg 9) */
+       /* copyfrom fname (arg 10) */
        f=sql_create_func_(sa, "copyfrom", "sql", "copy_from",
-               list_append( list_append( list_append( list_append( 
list_append(list_append (list_append (list_append(list_append(sa_list(sa), 
+               list_append( list_append( list_append( list_append( 
list_append(list_append (list_append 
(list_append(list_append(list_append(sa_list(sa),
                        create_arg(sa, NULL, sql_create_subtype(sa, STR, 0, 0), 
ARG_IN)), 
                        create_arg(sa, NULL, sql_create_subtype(sa, STR, 0, 0), 
ARG_IN)), 
                        create_arg(sa, NULL, sql_create_subtype(sa, STR, 0, 0), 
ARG_IN)), 
@@ -1771,7 +1771,8 @@ sqltypeinit( sql_allocator *sa)
                        create_arg(sa, NULL, sql_create_subtype(sa, STR, 0, 0), 
ARG_IN)), 
                        create_arg(sa, NULL, sql_create_subtype(sa, LNG, 0, 0), 
ARG_IN)), 
                        create_arg(sa, NULL, sql_create_subtype(sa, LNG, 0, 0), 
ARG_IN)), 
-                       create_arg(sa, NULL, sql_create_subtype(sa, INT, 0, 0), 
ARG_IN)), sres, FALSE, F_UNION, SCALE_FIX);
+                       create_arg(sa, NULL, sql_create_subtype(sa, INT, 0, 0), 
ARG_IN)),
+                       create_arg(sa, NULL, sql_create_subtype(sa, STR, 0, 0), 
ARG_IN)), sres, FALSE, F_UNION, SCALE_FIX);
        f->varres = 1;
 
        /* bincopyfrom */
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
@@ -1136,7 +1136,7 @@ table_column_types(sql_allocator *sa, sq
 }
 
 static sql_rel *
-rel_import(mvc *sql, sql_table *t, char *tsep, char *rsep, char *ssep, char 
*ns, char *filename, lng nr, lng offset, int locked, int best_effort)
+rel_import(mvc *sql, sql_table *t, char *tsep, char *rsep, char *ssep, char 
*ns, char *filename, lng nr, lng offset, int locked, int best_effort, dlist 
*fwf_widths)
 {
        sql_rel *res;
        list *exps, *args;
@@ -1144,7 +1144,8 @@ rel_import(mvc *sql, sql_table *t, char 
        sql_subtype tpe;
        sql_exp *import;
        sql_schema *sys = mvc_bind_schema(sql, "sys");
-       sql_subfunc *f = sql_find_func(sql->sa, sys, "copyfrom", 9, F_UNION, 
NULL); 
+       sql_subfunc *f = sql_find_func(sql->sa, sys, "copyfrom", 10, F_UNION, 
NULL);
+       char* fwf_string = NULL;
        
        if (!f) /* we do expect copyfrom to be there */
                return NULL;
@@ -1157,16 +1158,37 @@ rel_import(mvc *sql, sql_table *t, char 
                exp_atom_str(sql->sa, ssep, &tpe)), 
                exp_atom_str(sql->sa, ns, &tpe));
 
+       if (fwf_widths && dlist_length(fwf_widths) > 0) {
+               dnode *dn;
+               int ncol = 0;
+               fwf_string = GDKmalloc(20 * dlist_length(fwf_widths) + 1); // a 
64 bit int needs 19 characters in decimal representation plus the separator
+               if (!fwf_string) {
+                       return NULL;
+               }
+               char* fwf_string_cur = fwf_string;
+               for (dn = fwf_widths->h; dn; dn = dn->next) {
+                       fwf_string_cur += sprintf(fwf_string_cur, LLFMT"|", 
dn->data.l_val);
+                       ncol++;
+               }
+               if(list_length(f->res) != ncol) {
+                       (void) sql_error(sql, 02, "3F000!COPY INTO: fixed width 
import for %d columns but %d widths given.", list_length(f->res), ncol);
+                       return NULL;
+               }
+               *fwf_string_cur = '\0';
+       }
+
        append( args, exp_atom_str(sql->sa, filename, &tpe)); 
        import = exp_op(sql->sa,  
        append(
                append(
                        append( 
-                               append( args, 
-                                       exp_atom_lng(sql->sa, nr)), 
-                                       exp_atom_lng(sql->sa, offset)), 
-                                       exp_atom_int(sql->sa, locked)),
-                                       exp_atom_int(sql->sa, best_effort)), 
f); 
+                               append(
+                                       append( args,
+                                               exp_atom_lng(sql->sa, nr)),
+                                               exp_atom_lng(sql->sa, offset)),
+                                               exp_atom_int(sql->sa, locked)),
+                                               exp_atom_int(sql->sa, 
best_effort)),
+                                               exp_atom_str(sql->sa, 
fwf_string, &tpe)), f);
        
        exps = new_exp_list(sql->sa);
        for (n = t->columns.set->h; n; n = n->next) {
@@ -1179,7 +1201,7 @@ rel_import(mvc *sql, sql_table *t, char 
 }
 
 static sql_rel *
-copyfrom(mvc *sql, dlist *qname, dlist *columns, dlist *files, dlist *headers, 
dlist *seps, dlist *nr_offset, str null_string, int locked, int best_effort, 
int constraint)
+copyfrom(mvc *sql, dlist *qname, dlist *columns, dlist *files, dlist *headers, 
dlist *seps, dlist *nr_offset, str null_string, int locked, int best_effort, 
int constraint, dlist *fwf_widths)
 {
        sql_rel *rel = NULL;
        char *sname = qname_schema(qname);
@@ -1194,7 +1216,6 @@ copyfrom(mvc *sql, dlist *qname, dlist *
        lng offset = (nr_offset)?nr_offset->h->next->data.l_val:0;
        list *collist;
        int reorder = 0;
-
        assert(!nr_offset || nr_offset->h->type == type_lng);
        assert(!nr_offset || nr_offset->h->next->type == type_lng);
        if (sname && !(s=mvc_bind_schema(sql, sname))) {
@@ -1296,7 +1317,7 @@ copyfrom(mvc *sql, dlist *qname, dlist *
                                return sql_error(sql, 02, "COPY INTO: filename 
must "
                                                "have absolute path: %s", 
fname);
 
-                       nrel = rel_import(sql, nt, tsep, rsep, ssep, ns, fname, 
nr, offset, locked, best_effort);
+                       nrel = rel_import(sql, nt, tsep, rsep, ssep, ns, fname, 
nr, offset, locked, best_effort, fwf_widths);
 
                        if (!rel)
                                rel = nrel;
@@ -1306,7 +1327,7 @@ copyfrom(mvc *sql, dlist *qname, dlist *
                                return rel;
                }
        } else {
-               rel = rel_import(sql, nt, tsep, rsep, ssep, ns, NULL, nr, 
offset, locked, best_effort);
+               rel = rel_import(sql, nt, tsep, rsep, ssep, ns, NULL, nr, 
offset, locked, best_effort, NULL);
        }
        if (headers) {
                dnode *n;
@@ -1581,7 +1602,8 @@ rel_updates(mvc *sql, symbol *s)
                                
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.i_val, 
-                               
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->data.i_val,
+                               
l->h->next->next->next->next->next->next->next->next->next->next->data.lval);
                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
@@ -342,6 +342,8 @@ int yydebug=1;
        assignment_commalist
        opt_column_list
        column_commalist_parens
+       opt_fwf_widths
+       fwf_widthlist
        opt_header_list
        header_list
        header
@@ -599,7 +601,7 @@ SQLCODE SQLERROR UNDER WHENEVER
 
 %token CASE WHEN THEN ELSE NULLIF COALESCE IF ELSEIF WHILE DO
 %token ATOMIC BEGIN END
-%token COPY RECORDS DELIMITERS STDIN STDOUT
+%token COPY RECORDS DELIMITERS STDIN STDOUT FWF
 %token INDEX
 
 %token AS TRIGGER OF BEFORE AFTER ROW STATEMENT sqlNEW OLD EACH REFERENCING
@@ -2481,7 +2483,7 @@ opt_to_savepoint:
  ;
 
 copyfrom_stmt:
-    COPY opt_nr INTO qname opt_column_list FROM string_commalist 
opt_header_list opt_seps opt_null_string opt_locked opt_best_effort 
opt_constraint
+    COPY opt_nr INTO qname opt_column_list FROM string_commalist 
opt_header_list opt_seps opt_null_string opt_locked opt_best_effort 
opt_constraint opt_fwf_widths
        { dlist *l = L();
          append_list(l, $4);
          append_list(l, $5);
@@ -2493,6 +2495,7 @@ copyfrom_stmt:
          append_int(l, $11);
          append_int(l, $12);
          append_int(l, $13);
+         append_list(l, $14);
          $$ = _symbol_create_list( SQL_COPYFROM, l ); }
   | COPY opt_nr INTO qname opt_column_list FROM STDIN  opt_header_list 
opt_seps opt_null_string opt_locked opt_best_effort opt_constraint
        { dlist *l = L();
@@ -2532,7 +2535,22 @@ copyfrom_stmt:
          append_string(l, $6);
          $$ = _symbol_create_list( SQL_COPYTO, l ); }
   ;
-
+  
+
+
+opt_fwf_widths:
+       /* empty */             { $$ = NULL; }
+| FWF '(' fwf_widthlist ')' { $$ = $3; }
+ 
+ ;
+ 
+ fwf_widthlist:
+    poslng             { $$ = append_lng(L(), $1); }
+ |  fwf_widthlist ',' poslng
+                       { $$ = append_lng($1, $3); }
+ ;
+
+ 
 opt_header_list:
        /* empty */             { $$ = NULL; }
  | '(' header_list ')'         { $$ = $2; }
diff --git a/sql/server/sql_scan.c b/sql/server/sql_scan.c
--- a/sql/server/sql_scan.c
+++ b/sql/server/sql_scan.c
@@ -176,6 +176,8 @@ scanner_init_keywords(void)
        keywords_insert("FOR", FOR);
        keywords_insert("FOREIGN", FOREIGN);
        keywords_insert("FROM", FROM);
+       keywords_insert("FWF", FWF);
+
        keywords_insert("REFERENCES", REFERENCES);
 
        keywords_insert("MATCH", MATCH);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to