Changeset: e61ac4dd3f9b for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/e61ac4dd3f9b Modified Files: clients/ChangeLog.Jan2022 clients/mapiclient/mclient.c Branch: Jan2022 Log Message:
Fixed problem in SQL/client interaction in COPY INTO FROM STDIN. The problem is, at the end of a query, SQL reads any remaining white space (including newlines). If the COPY INTO buffer ends right after the semicolon, the following newline is not read here, but instead during CSV file processing, which then barfs. Our solution is to not send a semicolon at the end of a buffer but instead postpone it until the next chunk. diffs (81 lines): diff --git a/clients/ChangeLog.Jan2022 b/clients/ChangeLog.Jan2022 --- a/clients/ChangeLog.Jan2022 +++ b/clients/ChangeLog.Jan2022 @@ -1,3 +1,9 @@ # ChangeLog file for clients # This file is updated with Maddlog +* Tue May 31 2022 Sjoerd Mullender <[email protected]> +- Fixed a bug where when the semicolon at the end of a COPY INTO query + that reads from STDIN is at exactly a 10240 byte boundary in a file, + the data isn't read as input for the COPY INTO but instead as a new + SQL query. + diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c --- a/clients/mapiclient/mclient.c +++ b/clients/mapiclient/mclient.c @@ -2042,6 +2042,7 @@ static bool doFileBulk(Mapi mid, stream *fp) { char *buf = NULL; + size_t semicolon1 = 0, semicolon2 = 0; ssize_t length; MapiHdl hdl = mapi_get_active(mid); MapiMsg rc = MOK; @@ -2064,18 +2065,28 @@ doFileBulk(Mapi mid, stream *fp) break; length = 0; buf[0] = 0; - } else if ((length = mnstr_read(fp, buf, 1, bufsize)) <= 0) { - /* end of file or error */ - if (hdl == NULL) + } else { + if ((length = mnstr_read(fp, buf, 1, bufsize)) < 0) { + /* error */ + errseen = true; break; /* nothing more to do */ - buf[0] = 0; - length = 0; /* handle error like EOF */ - } else { - buf[length] = 0; - if (strlen(buf) < (size_t) length) { - mnstr_printf(stderr_stream, "NULL byte in input\n"); - errseen = true; - break; + } else { + buf[length] = 0; + if (length == 0) { + /* end of file */ + if (semicolon2 == 0 && hdl == NULL) + break; /* nothing more to do */ + } else { + if (strlen(buf) < (size_t) length) { + mnstr_printf(stderr_stream, "NULL byte in input\n"); + errseen = true; + break; + } + while (length > 1 && buf[length - 1] == ';') { + semicolon1++; + buf[--length] = 0; + } + } } } timerResume(); @@ -2085,7 +2096,15 @@ doFileBulk(Mapi mid, stream *fp) } assert(hdl != NULL); - mapi_query_part(hdl, buf, (size_t) length); + while (semicolon2 > 0) { + mapi_query_part(hdl, ";", 1); + CHECK_RESULT(mid, hdl, buf, fp); + semicolon2--; + } + semicolon2 = semicolon1; + semicolon1 = 0; + if (length > 0) + mapi_query_part(hdl, buf, (size_t) length); CHECK_RESULT(mid, hdl, buf, fp); /* if not at EOF, make sure there is a newline in the _______________________________________________ checkin-list mailing list -- [email protected] To unsubscribe send an email to [email protected]
