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

Reply via email to