Changeset: f150afe932d0 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/f150afe932d0 Branch: default Log Message:
merge diffs (115 lines): diff --git a/MonetDB.spec b/MonetDB.spec --- a/MonetDB.spec +++ b/MonetDB.spec @@ -302,8 +302,8 @@ This package contains the files needed t Summary: MonetDB ODBC driver Group: Applications/Databases Requires: %{name}-client%{?_isa} = %{version}-%{release} -Requires(post): unixODBC -Requires(postun): unixODBC +Requires(post): %{_bindir}/odbcinst +Requires(postun): %{_bindir}/odbcinst %description client-odbc MonetDB is a database management system that is developed from a 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 @@ -1496,7 +1496,7 @@ copyfrom(sql_query *query, dlist *qname, char *tname = qname_schema_object(qname); sql_table *t = NULL, *nt = NULL; const char *tsep = seps->h->data.sval; - const char *rsep = seps->h->next->data.sval; + char *rsep = seps->h->next->data.sval; // not const, might need adjusting const char *ssep = (seps->h->next->next)?seps->h->next->next->data.sval:NULL; const char *ns = (null_string)?null_string:"null"; lng nr = (nr_offset)?nr_offset->h->data.l_val:-1; @@ -1506,10 +1506,15 @@ copyfrom(sql_query *query, dlist *qname, assert(!nr_offset || nr_offset->h->type == type_lng); assert(!nr_offset || nr_offset->h->next->type == type_lng); - if (strstr(rsep, "\r\n") != NULL) + if (strcmp(rsep, "\r\n") == 0) { + // silently fix it + rsep[0] = '\n'; + rsep[1] = '\0'; + } else if (strstr(rsep, "\r\n") != NULL) { return sql_error(sql, 02, SQLSTATE(42000) "COPY INTO: record separator contains '\\r\\n' but " - "in the input stream, '\\r\\n' is being normalized into '\\n'"); + "that will never match, use '\\n' instead"); + } t = find_table_or_view_on_scope(sql, NULL, sname, tname, "COPY INTO", false); if (insert_allowed(sql, t, tname, "COPY INTO", "copy into") == NULL) diff --git a/sql/test/copy/Tests/All b/sql/test/copy/Tests/All --- a/sql/test/copy/Tests/All +++ b/sql/test/copy/Tests/All @@ -15,3 +15,4 @@ incorrect_columns columns no_escape no_escape2 +crlf_normalization diff --git a/sql/test/copy/Tests/crlf_normalization.SQL.py b/sql/test/copy/Tests/crlf_normalization.SQL.py new file mode 100644 --- /dev/null +++ b/sql/test/copy/Tests/crlf_normalization.SQL.py @@ -0,0 +1,58 @@ +import os, re, sys, tempfile +try: + from MonetDBtesting import process +except ImportError: + import process + +# Use a Python test because we're testing LF / CR LF handling and we don't +# want editors or version control systems messing with our line endings + +def r_escape(s): + return "r'" + s.replace("'", "''") + "' " + +def testdata(prefix,line_sep): + prefix = "crlf_test_" + prefix + "_" + lines = [ b"1,one", b"3,two", b"5,three" ] + text = bytes(line_sep, "ascii").join([*lines, b'']) + f = tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=".csv") + name = f.name + f.write(text) + f.close() + return name, text + +def run_test(name, data_delimiter, copy_delimiter): + file_name, test_data = testdata(name, data_delimiter) + script = f""" + DROP TABLE IF EXISTS foo; + CREATE TABLE foo(i INT, t TEXT); + COPY INTO foo FROM {r_escape(file_name)} + USING DELIMITERS ',', '{copy_delimiter}'; + SELECT i, LENGTH(t) FROM foo; + """ + with process.client('sql', stdin=process.PIPE, stdout=process.PIPE, stderr=process.PIPE) as c: + out, err = c.communicate(script) + reduced = "\n".join(re.sub(r"\s+", "", line) for line in out.splitlines() if line.startswith("[")) + expected = "[3]\n[1,3]\n[3,3]\n[5,5]" + if reduced != expected: + print("TEST: ", name, file=sys.stderr) + print("\nLINE DELIMITER: ", repr(data_delimiter), sep='', file=sys.stderr) + print("\nFILE CONTENTS: ", repr(test_data), sep='', file=sys.stderr) + print("\nSCRIPT:\n", script, sep='', file=sys.stderr) + print("\nEXPECTED:\n", expected, sep='', file=sys.stderr) + print("\nGOT:\n", reduced, sep='', file=sys.stderr) + print("\nFULL STDERR:\n", err, sep='', file=sys.stderr) + print("\nFULL OUTPUT:\n", out, sep='', file=sys.stderr) + raise SystemExit("Test failed") + os.remove(file_name) + +# Load unix endings while asking for Unix endings. +run_test("unix", "\n", r"\n") + +# Load dos endings while asking for dos endings +run_test("dos", "\n", r"\n") + +# Load dos endings while asking for unix endings +run_test("dos_as_unix", "\r\n", r"\n") + +# Load unix endings while asking for dos endings +run_test("unix_as_dos", "\n", r"\r\n") _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list