Changeset: d20955ed774e for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d20955ed774e Added Files: sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.sql sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.stable.err sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.stable.out Modified Files: clients/Tests/exports.stable.out gdk/gdk_atoms.c gdk/gdk_atoms.h monetdb5/modules/mal/tablet.h sql/backends/monet5/sql_result.c sql/test/BugTracker-2013/Tests/All Branch: default Log Message:
Merge with Jan2014 branch. diffs (truncated from 417 to 300 lines): diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -417,8 +417,8 @@ int dlclose(void *handle); char *dlerror(void); void *dlopen(const char *file, int mode); void *dlsym(void *handle, const char *name); -int escapedStr(char *dst, const char *src, int dstlen); -int escapedStrlen(const char *src); +int escapedStr(char *dst, const char *src, int dstlen, const char *sep1, const char *sep2, int quote); +int escapedStrlen(const char *src, const char *sep1, const char *sep2, int quote); int fltFromStr(const char *src, int *len, flt **dst); int fltToStr(str *dst, int *len, const flt *src); const flt flt_nil; diff --git a/gdk/gdk_atoms.c b/gdk/gdk_atoms.c --- a/gdk/gdk_atoms.c +++ b/gdk/gdk_atoms.c @@ -1391,15 +1391,18 @@ strFromStr(const char *src, int *len, ch #endif int -escapedStrlen(const char *src) +escapedStrlen(const char *src, const char *sep1, const char *sep2, int quote) { int end, sz = 0; + size_t sep1len, sep2len; + sep1len = sep1 ? strlen(sep1) : 0; + sep2len = sep2 ? strlen(sep2) : 0; for (end = 0; src[end]; end++) - if (src[end] == '\t' || - src[end] == '\n' || - src[end] == '\\' || - src[end] == '"') { + if (src[end] == '\\' || + src[end] == quote || + (sep1len && strncmp(src + end, sep1, sep1len) == 0) || + (sep2len && strncmp(src + end, sep2, sep2len) == 0)) { sz += 2; #ifndef ASCII_CHR } else if (src[end] == (char) '\302' && @@ -1423,36 +1426,50 @@ escapedStrlen(const char *src) } int -escapedStr(char *dst, const char *src, int dstlen) +escapedStr(char *dst, const char *src, int dstlen, const char *sep1, const char *sep2, int quote) { int cur = 0, l = 0; + size_t sep1len, sep2len; + sep1len = sep1 ? strlen(sep1) : 0; + sep2len = sep2 ? strlen(sep2) : 0; for (; src[cur] && l < dstlen; cur++) - if (src[cur] == '\t') { + if (!printable_chr(src[cur]) +#ifndef ASCII_CHR + || (src[cur] == '\302' && + 0200 <= (src[cur + 1] & 0377) && + ((int) src[cur + 1] & 0377) <= 0237) + || (cur > 0 && + src[cur - 1] == '\302' && + 0200 <= (src[cur] & 0377) && + (src[cur] & 0377) <= 0237) +#endif + ) { dst[l++] = '\\'; - dst[l++] = 't'; - } else if (src[cur] == '\n') { + switch (src[cur]) { + case '\t': + dst[l++] = 't'; + break; + case '\n': + dst[l++] = 'n'; + break; + case '\r': + dst[l++] = 'r'; + break; + case '\f': + dst[l++] = 'f'; + break; + default: + snprintf(dst + l, dstlen - l, "%03o", (unsigned char) src[cur]); + l += 3; + break; + } + } else if (src[cur] == '\\' || + src[cur] == quote || + (sep1len && strncmp(src + cur, sep1, sep1len) == 0) || + (sep2len && strncmp(src + cur, sep2, sep2len) == 0)) { dst[l++] = '\\'; - dst[l++] = 'n'; - } else if (src[cur] == '\\') { - dst[l++] = '\\'; - dst[l++] = '\\'; - } else if (src[cur] == '"') { - dst[l++] = '\\'; - dst[l++] = '"'; - } else if (!printable_chr(src[cur]) -#ifndef ASCII_CHR - || (src[cur] == '\302' && - 0200 <= (src[cur + 1] & 0377) && - ((int) src[cur + 1] & 0377) <= 0237) - || (cur > 0 && - src[cur - 1] == '\302' && - 0200 <= (src[cur] & 0377) && - (src[cur] & 0377) <= 0237) -#endif - ) { - snprintf(dst + l, dstlen - l, "\\%03o", (unsigned char) src[cur]); - l += 4; + dst[l++] = src[cur]; } else { dst[l++] = src[cur]; } @@ -1472,9 +1489,9 @@ strToStr(char **dst, int *len, const cha strncpy(*dst, "nil", *len); return 3; } else { - int sz = escapedStrlen(src); + int sz = escapedStrlen(src, NULL, NULL, '"'); atommem(char, sz + 3); - l = escapedStr((*dst) + 1, src, *len - 1); + l = escapedStr((*dst) + 1, src, *len - 1, NULL, NULL, '"'); l++; (*dst)[0] = (*dst)[l++] = '"'; (*dst)[l] = 0; diff --git a/gdk/gdk_atoms.h b/gdk/gdk_atoms.h --- a/gdk/gdk_atoms.h +++ b/gdk/gdk_atoms.h @@ -105,8 +105,8 @@ gdk_export int strToStr(str *dst, int *l gdk_export BUN strHash(const char *s); gdk_export int strLen(const char *s); gdk_export int strNil(const char *s); -gdk_export int escapedStrlen(const char *src); -gdk_export int escapedStr(char *dst, const char *src, int dstlen); +gdk_export int escapedStrlen(const char *src, const char *sep1, const char *sep2, int quote); +gdk_export int escapedStr(char *dst, const char *src, int dstlen, const char *sep1, const char *sep2, int quote); /* * @- nil values * All types have a single value designated as a NIL value. It diff --git a/monetdb5/modules/mal/tablet.h b/monetdb5/modules/mal/tablet.h --- a/monetdb5/modules/mal/tablet.h +++ b/monetdb5/modules/mal/tablet.h @@ -50,6 +50,7 @@ typedef struct Column_t { const char *name; /* column title */ const char *sep; + const char *rsep; int seplen; char *type; int adt; /* type index */ diff --git a/sql/backends/monet5/sql_result.c b/sql/backends/monet5/sql_result.c --- a/sql/backends/monet5/sql_result.c +++ b/sql/backends/monet5/sql_result.c @@ -547,8 +547,12 @@ static int Column *c = extra; char *dst; const char *src = a; - int l = (c->quote) ? escapedStrlen(src) : (int) strlen(src), l2 = 0; + int l = escapedStrlen(src, c->sep, c->rsep, c->quote), l2 = 0; + if (c->quote) + l = escapedStrlen(src, NULL, NULL, c->quote); + else + l = escapedStrlen(src, c->sep, c->rsep, 0); if (l + 3 > *len) { GDKfree(*buf); *len = 2 * l + 3; @@ -558,9 +562,9 @@ static int if (c->quote) { dst[0] = c->quote; l2 = 1; - l = escapedStr(dst + l2, src, *len - l2); + l = escapedStr(dst + l2, src, *len - l2, NULL, NULL, c->quote); } else { - strncpy(dst + l2, src, l); + l = escapedStr(dst + l2, src, *len - l2, c->sep, c->rsep, 0); } if (l2) { dst[l + l2] = c->quote; @@ -648,6 +652,7 @@ mvc_import_table(Client cntxt, mvc *m, b fmt[i].name = col->base.name; fmt[i].sep = (n->next) ? sep : rsep; + fmt[i].rsep = rsep; fmt[i].seplen = _strlen(fmt[i].sep); fmt[i].type = sql_subtype_string(&col->type); fmt[i].adt = ATOMindex(col->type.type->base.name); @@ -726,6 +731,7 @@ mvc_import_table(Client cntxt, mvc *m, b sql_error(m, 500, "%s", as.error); for (n = t->columns.set->h, i = 0; n; n = n->next, i++) { fmt[i].sep = NULL; + fmt[i].rsep = NULL; fmt[i].nullstr = NULL; } TABLETdestroy_format(&as); @@ -1127,6 +1133,7 @@ mvc_export_table(backend *b, stream *s, fmt[0].c = NULL; fmt[0].sep = (csv) ? btag : ""; + fmt[0].rsep = rsep; fmt[0].seplen = _strlen(fmt[0].sep); fmt[0].ws = 0; fmt[0].nullstr = NULL; @@ -1143,6 +1150,7 @@ mvc_export_table(backend *b, stream *s, if (csv) { fmt[i].sep = ((i - 1) < (t->nr_cols - 1)) ? sep : rsep; fmt[i].seplen = _strlen(fmt[i].sep); + fmt[i].rsep = rsep; } if (json) { res_col *p = t->cols + (i - 1); @@ -1156,13 +1164,16 @@ mvc_export_table(backend *b, stream *s, snprintf(bj, strlen(p->name) + 6, "{ %s , ", p->name); fmt[i - 1].sep = bj; fmt[i - 1].seplen = _strlen(fmt[i - 1].sep); + fmt[i - 1].rsep = NULL; } else if (i <= t->nr_cols) { fmt[i - 1].sep = p->name; fmt[i - 1].seplen = _strlen(fmt[i - 1].sep); + fmt[i - 1].rsep = NULL; } if (i == t->nr_cols) { fmt[i].sep = " }\n"; fmt[i].seplen = _strlen(fmt[i].sep); + fmt[i].rsep = NULL; } } fmt[i].type = ATOMname(fmt[i].c->ttype); @@ -1211,6 +1222,7 @@ mvc_export_table(backend *b, stream *s, } for (i = 0; i <= t->nr_cols; i++) { fmt[i].sep = NULL; + fmt[i].rsep = NULL; fmt[i].type = NULL; fmt[i].nullstr = NULL; } diff --git a/sql/test/BugTracker-2013/Tests/All b/sql/test/BugTracker-2013/Tests/All --- a/sql/test/BugTracker-2013/Tests/All +++ b/sql/test/BugTracker-2013/Tests/All @@ -55,6 +55,7 @@ python-explain.Bug-3380 case-orderby.Bug-3388 unop_vs_aggr.Bug-3885 singleton-median.Bug-3389 +copy-out-quote.Bug-3393 Cannot_Find_Column_Type.Bug-3394 case_when.Bug-3395 udf_error.Bug-3396 diff --git a/sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.sql b/sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.sql new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.sql @@ -0,0 +1,10 @@ +start transaction; +create table table3393 (a clob, b clob); +insert into table3393 values ('one|two', 'three"four'); +insert into table3393 values ('five\tsix', 'seven\neight'); +insert into table3393 values ('nine,ten', 'eleven\\twelve'); +select * from table3393; +copy select * from table3393 into stdout delimiters ',', '\n', '|'; +copy select * from table3393 into stdout delimiters '|', '\n', ','; +copy select * from table3393 into stdout; +rollback; diff --git a/sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.stable.err b/sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.stable.err new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2013/Tests/copy-out-quote.Bug-3393.stable.err @@ -0,0 +1,35 @@ +stderr of test 'copy-out-quote.Bug-3393` in directory 'sql/test/BugTracker-2013` itself: + + +# 10:58:27 > +# 10:58:27 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "mapi_open=true" "--set" "mapi_port=38193" "--set" "mapi_usock=/var/tmp/mtest-13320/.s.monetdb.38193" "--set" "monet_prompt=" "--forcemito" "--set" "mal_listing=2" "--dbpath=/ufs/sjoerd/Monet-candidate/var/MonetDB/mTests_sql_test_BugTracker-2013" "--set" "mal_listing=0" +# 10:58:27 > + +# builtin opt gdk_dbpath = /ufs/sjoerd/Monet-candidate/var/monetdb5/dbfarm/demo +# builtin opt gdk_debug = 0 +# builtin opt gdk_vmtrim = yes +# 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 = 38193 +# cmdline opt mapi_usock = /var/tmp/mtest-13320/.s.monetdb.38193 +# cmdline opt monet_prompt = +# cmdline opt mal_listing = 2 +# cmdline opt gdk_dbpath = /ufs/sjoerd/Monet-candidate/var/MonetDB/mTests_sql_test_BugTracker-2013 +# cmdline opt mal_listing = 0 + +# 10:58:27 > +# 10:58:27 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-13320" "--port=38193" +# 10:58:27 > + _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list