Changeset: 33cfedf29e90 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=33cfedf29e90
Added Files:
        sql/test/copy/Tests/incorrect_columns.stable.err
        sql/test/copy/Tests/incorrect_columns.stable.out
Modified Files:
        monetdb5/modules/mal/tablet.c
        sql/test/copy/Tests/incorrect_columns.sql
        sql/test/copy/Tests/key_copy.sql
        sql/test/copy/Tests/key_copy.stable.err
Branch: Jul2015
Log Message:

Fixing errors in Best Effort loading
- properly handle the case of less/more fields in a line
The line is added to the reject list
- properly construct the rejects message
- continue parsing lines in best-effort mode


diffs (truncated from 397 to 300 lines):

diff --git a/monetdb5/modules/mal/tablet.c b/monetdb5/modules/mal/tablet.c
--- a/monetdb5/modules/mal/tablet.c
+++ b/monetdb5/modules/mal/tablet.c
@@ -838,14 +838,14 @@ mycpstr(char *t, const char *s)
 }
 
 static str
-SQLload_error(READERtask *task, lng idx)
+SQLload_error(READERtask *task, lng idx, unsigned int attrs)
 {
        str line;
        char *s;
        size_t sz = 0;
        unsigned int i;
 
-       for (i = 0; i < task->as->nr_attrs; i++) {
+       for (i = 0; i < attrs; i++) {
                if (task->fields[i][idx])
                        sz += mystrlen(task->fields[i][idx]);
                sz += task->seplen;
@@ -856,10 +856,10 @@ SQLload_error(READERtask *task, lng idx)
                tablet_error(task, idx, int_nil, "SQLload malloc error", 
"SQLload_error");
                return 0;
        }
-       for (i = 0; i < task->as->nr_attrs; i++) {
+       for (i = 0; i < attrs; i++) {
                if (task->fields[i][idx])
                        s = mycpstr(s, task->fields[i][idx]);
-               if (i < task->as->nr_attrs - 1)
+               if (i < attrs - 1)
                        s = mycpstr(s, task->csep);
        }
        strcat(line, task->rsep);
@@ -893,7 +893,7 @@ SQLinsert_val(READERtask *task, int col,
        if (adt == NULL) {
                lng row = task->cnt + idx + 1;
                snprintf(buf, BUFSIZ, "'%s' expected", fmt->type);
-               err = SQLload_error(task, idx);
+               err = SQLload_error(task, idx, task->as->nr_attrs);
                if (task->rowerror) {
                        MT_lock_set(&errorlock, "insert_val");
                        col++;
@@ -925,7 +925,7 @@ SQLinsert_val(READERtask *task, int col,
                BUNappend(task->cntxt->error_row, &row, FALSE);
                BUNappend(task->cntxt->error_fld, &col, FALSE);
                BUNappend(task->cntxt->error_msg, "insert failed", FALSE);
-               err = SQLload_error(task, idx);
+               err = SQLload_error(task, idx,task->as->nr_attrs);
                BUNappend(task->cntxt->error_input, err, FALSE);
                GDKfree(err);
                task->rowerror[row - 1]++;
@@ -953,8 +953,10 @@ SQLworker_column(READERtask *task, int c
        MT_lock_unset(&mal_copyLock, "tablet insert value");
 
        for (i = 0; i < task->top[task->cur]; i++) {
-               if (!fmt[col].skip && SQLinsert_val(task, col, i) < 0)
-                       return -1;
+               if (!fmt[col].skip && SQLinsert_val(task, col, i) < 0){
+                       if(task->besteffort == 0)
+                               return -1;
+               }
        }
 
        return 0;
@@ -984,10 +986,11 @@ SQLload_parse_line(READERtask *task, int
        //mnstr_printf(GDKout, "#SQL break line id %d  state %d\n%s", task->id, 
idx, line);
 #endif
        assert(idx < task->top[task->cur]);
+       assert(line);
        errmsg[0] = 0;
 
        if (task->quote || task->seplen != 1) {
-               for (i = 0; i < as->nr_attrs; i++) {
+               for (i = 0; *line && i < as->nr_attrs; i++) {
                        task->fields[i][idx] = line;
                        /* recognize fields starting with a quote, keep them */
                        if (*line == task->quote) {
@@ -1000,7 +1003,7 @@ SQLload_parse_line(READERtask *task, int
                                mnstr_printf(GDKout, "after #1 %s\n", s);
 #endif
                                if (!line) {
-                                       errline = SQLload_error(task, 
task->top[task->cur]);
+                                       errline = SQLload_error(task, idx, i+1);
                                        snprintf(errmsg, BUFSIZ, "Quote (%c) 
missing", task->quote);
                                        tablet_error(task, idx, (int) i, 
errmsg, errline);
                                        GDKfree(errline);
@@ -1023,8 +1026,8 @@ SQLload_parse_line(READERtask *task, int
 
                        /* not enough fields */
                        if (i < as->nr_attrs - 1) {
-                               errline = SQLload_error(task, 
task->top[task->cur]);
-                               snprintf(errmsg, BUFSIZ, "Separator missing 
'%s' ", fmt->sep);
+                               errline = SQLload_error(task, idx, i+1);
+                               snprintf(errmsg, BUFSIZ, "Column value "BUNFMT" 
missing ", i+1);
                                tablet_error(task, idx, (int) i, errmsg, 
errline);
                                GDKfree(errline);
                                error++;
@@ -1033,18 +1036,14 @@ SQLload_parse_line(READERtask *task, int
                                for (; i < as->nr_attrs; i++)
                                        task->fields[i][idx] = NULL;
                                i--;
-                       }
+                       } 
                  endoffieldcheck:
                        ;
                        /* check for user defined NULL string */
                        if (!fmt->skip && fmt->nullstr && task->fields[i][idx] 
&& strncasecmp(task->fields[i][idx], fmt->nullstr, fmt->null_length + 1) == 0)
                                task->fields[i][idx] = 0;
                }
-#ifdef _DEBUG_TABLET_
-               if (error)
-                       mnstr_printf(GDKout, "#line break failed %d:%s\n", idx, 
line);
-#endif
-               return error ? -1 : 0;
+               goto endofline;
        }
        assert(!task->quote);
        assert(task->seplen == 1);
@@ -1068,8 +1067,8 @@ SQLload_parse_line(READERtask *task, int
 #endif
                /* not enough fields */
                if (i < as->nr_attrs - 1) {
-                       errline = SQLload_error(task, task->top[task->cur]);
-                       snprintf(errmsg, BUFSIZ, "Separator missing '%s' ", 
fmt->sep);
+                       errline = SQLload_error(task, idx,i+1);
+                       snprintf(errmsg, BUFSIZ, "Column value "BUNFMT" 
missing",i+1);
                        tablet_error(task, idx, (int) i, errmsg, errline);
                        GDKfree(errline);
                        error++;
@@ -1085,6 +1084,15 @@ SQLload_parse_line(READERtask *task, int
                        task->fields[i][idx] = 0;
                }
        }
+endofline:
+       /* check for too many values as well*/
+       if (*line && i == as->nr_attrs) {
+               errline = SQLload_error(task, idx, task->as->nr_attrs);
+               snprintf(errmsg, BUFSIZ, "Leftover data '%s'",line);
+               tablet_error(task, idx, (int) i, errmsg, errline);
+               GDKfree(errline);
+               error++;
+       }
 #ifdef _DEBUG_TABLET_
        if (error)
                mnstr_printf(GDKout, "#line break failed %d:%s\n", idx, line);
@@ -1125,8 +1133,10 @@ SQLworker(void *arg)
                        for (j = piece * task->id; j < task->top[task->cur] && 
j < piece * (task->id +1); j++)
                                if (task->lines[task->cur][j]) {
                                        if (SQLload_parse_line(task, j) < 0) {
-                                               task->error++;
-                                               break;
+                                               task->errorcnt++;
+                                               // early break unless best 
effort
+                                               if(task->besteffort == 0)
+                                                       break;
                                        }
                                }
                        task->wtime = GDKusec() - t0;
@@ -1550,7 +1560,7 @@ SQLproducer(void *p)
 BUN
 SQLload_file(Client cntxt, Tablet *as, bstream *b, stream *out, char *csep, 
char *rsep, char quote, lng skip, lng maxrow, int best)
 {
-       BUN cnt = 0, cntstart = 0;
+       BUN cnt = 0, cntstart = 0, leftover = 0;
        int res = 0;            /* < 0: error, > 0: success, == 0: continue 
processing */
        int j;
        BUN i, attr;
@@ -1794,7 +1804,7 @@ SQLload_file(Client cntxt, Tablet *as, b
 #define trimerrors(TYPE)                                                       
                                        \
                do {                                                            
                                                        \
                        TYPE *src, *dst;                                        
                                                \
-                       BUN leftover= BATcount(task->as->format[attr].c);       
                \
+                       leftover= BATcount(task->as->format[attr].c);           
        \
                        limit = leftover - cntstart;                            
                                \
                        dst =src= (TYPE *) 
BUNtloc(task->as->format[attr].ci,cntstart); \
                        for(j = 0; j < (int) limit; j++, src++){                
                        \
@@ -1813,8 +1823,14 @@ SQLload_file(Client cntxt, Tablet *as, b
 #endif
                if (best && BATcount(as->format[0].c)) {
                        BUN limit;
+                       int width;
+
                        for (attr = 0; attr < as->nr_attrs; attr++) {
-                               switch (ATOMsize(as->format[attr].c->ttype)) {
+                               if( as->format[attr].c->ttype == TYPE_str)
+                                       width = as->format[attr].c->T->width;
+                               else
+                                       width = 
ATOMsize(as->format[attr].c->ttype);
+                               switch (width){
                                case 1:
                                        trimerrors(unsigned char);
                                        break;
diff --git a/sql/test/copy/Tests/incorrect_columns.sql 
b/sql/test/copy/Tests/incorrect_columns.sql
--- a/sql/test/copy/Tests/incorrect_columns.sql
+++ b/sql/test/copy/Tests/incorrect_columns.sql
@@ -1,12 +1,14 @@
 -- test the situation where the number of column values are incorrect
 create table t_columns(i int, t string);
 
-copy 5 records into t_columns from stdin delimiters ',','\n' best effort;
+copy 7 records into t_columns from stdin delimiters ',','\n' best effort;
 1,hello
 2
 no tag
-3,too much, data
+3,too much,xyz
 4,world
+5,wereld
+6,maan
 
 select * from t_columns;
 
diff --git a/sql/test/copy/Tests/incorrect_columns.stable.err 
b/sql/test/copy/Tests/incorrect_columns.stable.err
new file mode 100644
--- /dev/null
+++ b/sql/test/copy/Tests/incorrect_columns.stable.err
@@ -0,0 +1,37 @@
+stderr of test 'incorrect_columns` in directory 'sql/test/copy` itself:
+
+
+# 08:11:47 >  
+# 08:11:47 >  "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" 
"mapi_open=true" "--set" "mapi_port=37579" "--set" 
"mapi_usock=/var/tmp/mtest-26664/.s.monetdb.37579" "--set" "monet_prompt=" 
"--forcemito" "--set" "mal_listing=2" 
"--dbpath=/export/scratch1/mk/Jul2015//Linux/var/MonetDB/mTests_sql_test_copy" 
"--set" "mal_listing=0" "--set" "embedded_r=yes"
+# 08:11:47 >  
+
+# builtin opt  gdk_dbpath = 
/export/scratch1/mk/Jul2015//Linux/var/monetdb5/dbfarm/demo
+# builtin opt  gdk_debug = 0
+# builtin opt  gdk_vmtrim = no
+# builtin opt  monet_prompt = >
+# builtin opt  monet_daemon = no
+# builtin opt  mapi_port = 50000
+# builtin opt  mapi_open = false
+# builtin opt  mapi_autosense = false
+# builtin opt  sql_optimizer = default_pipe
+# builtin opt  sql_debug = 0
+# cmdline opt  gdk_nr_threads = 0
+# cmdline opt  mapi_open = true
+# cmdline opt  mapi_port = 37579
+# cmdline opt  mapi_usock = /var/tmp/mtest-26664/.s.monetdb.37579
+# cmdline opt  monet_prompt = 
+# cmdline opt  mal_listing = 2
+# cmdline opt  gdk_dbpath = 
/export/scratch1/mk/Jul2015//Linux/var/MonetDB/mTests_sql_test_copy
+# cmdline opt  mal_listing = 0
+# cmdline opt  embedded_r = yes
+# cmdline opt  gdk_debug = 536870922
+
+# 08:11:47 >  
+# 08:11:47 >  "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" 
"--host=/var/tmp/mtest-26664" "--port=37579"
+# 08:11:47 >  
+
+
+# 16:14:08 >  
+# 16:14:08 >  "Done."
+# 16:14:08 >  
+
diff --git a/sql/test/copy/Tests/incorrect_columns.stable.out 
b/sql/test/copy/Tests/incorrect_columns.stable.out
new file mode 100644
--- /dev/null
+++ b/sql/test/copy/Tests/incorrect_columns.stable.out
@@ -0,0 +1,99 @@
+stdout of test 'incorrect_columns` in directory 'sql/test/copy` itself:
+
+
+# 08:11:47 >  
+# 08:11:47 >  "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" 
"mapi_open=true" "--set" "mapi_port=37579" "--set" 
"mapi_usock=/var/tmp/mtest-26664/.s.monetdb.37579" "--set" "monet_prompt=" 
"--forcemito" "--set" "mal_listing=2" 
"--dbpath=/export/scratch1/mk/Jul2015//Linux/var/MonetDB/mTests_sql_test_copy" 
"--set" "mal_listing=0" "--set" "embedded_r=yes"
+# 08:11:47 >  
+
+# MonetDB 5 server v11.21.2
+# This is an unreleased version
+# Serving database 'mTests_sql_test_copy', using 8 threads
+# Compiled for x86_64-unknown-linux-gnu/64bit with 64bit OIDs and 128bit 
integers dynamically linked
+# Found 15.590 GiB available main-memory.
+# Copyright (c) 1993-July 2008 CWI.
+# Copyright (c) August 2008-2015 MonetDB B.V., all rights reserved
+# Visit http://www.monetdb.org/ for further information
+# Listening for connection requests on mapi:monetdb://vienna.ins.cwi.nl:37579/
+# Listening for UNIX domain connection requests on 
mapi:monetdb:///var/tmp/mtest-26664/.s.monetdb.37579
+# MonetDB/GIS module loaded
+# Start processing logs sql/sql_logs version 52200
+# Finished processing logs sql/sql_logs
+# MonetDB/SQL module loaded
+# MonetDB/R   module loaded
+
+Ready.
+# SQL catalog created, loading sql scripts once
+# loading sql script: 09_like.sql
+# loading sql script: 10_math.sql
+# loading sql script: 11_times.sql
+# loading sql script: 12_url.sql
+# loading sql script: 13_date.sql
+# loading sql script: 14_inet.sql
+# loading sql script: 15_querylog.sql
+# loading sql script: 16_tracelog.sql
+# loading sql script: 17_temporal.sql
+# loading sql script: 20_vacuum.sql
+# loading sql script: 21_dependency_functions.sql
+# loading sql script: 22_clients.sql
+# loading sql script: 23_skyserver.sql
+# loading sql script: 24_zorder.sql
+# loading sql script: 25_debug.sql
+# loading sql script: 26_sysmon.sql
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to