diff --git a/Makefile b/Makefile index 5b42d55..511c42e 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,21 @@ test: @echo "Running ODBCLoader Test Suite" @echo "=========================================" @echo "" + @echo "[*] Running Copy Test..." + @echo "" + @$(VSQL) -f tests/copy_test.sql 2>&1 | tee $(TMPDIR)/copy_test.out | perl -pe 's/^vsql:[\/_:\w\.]* /vsql: /; \ + s/\[ODBC[^\]]*\]/[...]/g; \ + s/\[mysql[^\]]*\]/[...]/g; \ + s/(Error parsing .* )\(.*\)$$/$$1(...)/; \ + s/mariadb/MySQL/ig; ' + @echo "" + @echo "[*] Validating copy test output..." + @diff -u tests/expected/copy_test.out <(perl -pe 's/^vsql:[\/_:\w\.]* /vsql: /; \ + s/\[ODBC[^\]]*\]/[...]/g; \ + s/\[mysql[^\]]*\]/[...]/g; \ + s/(Error parsing .* )\(.*\)$$/$$1(...)/; \ + s/mariadb/MySQL/ig; ' $(TMPDIR)/copy_test.out) && echo "[✓] Copy test validation passed" || (echo "[✗] Copy test validation failed" && exit 1) + @echo "" @echo "[*] Running Federated Queries Test..." @echo "" @$(VSQL) -f tests/federated_queries.sql 2>&1 | tee $(TMPDIR)/federated_queries.out | perl -pe 's/^vsql:[\/_:\w\.]* /vsql: /; \ diff --git a/ODBCLoader.cpp b/ODBCLoader.cpp index 95aaa76..7460aaf 100644 --- a/ODBCLoader.cpp +++ b/ODBCLoader.cpp @@ -574,9 +574,11 @@ class ODBCLoader : public UDParser { // Check "hidden" parameters __query_col_name__ and __query_col_idx__ to filter out columns if ( src_cfilter ) { - if (srvInterface.getParamReader().containsParameter("__query_col_name__")) { - if (srvInterface.getParamReader().containsParameter("__query_col_idx__")) { - colInTable = (int)colInfo.getColumnCount() ; + // Only column-filter when the param is actually non-empty, a plain COPY sends it empty. + if (srvInterface.getParamReader().containsParameter("__query_col_name__") && + !srvInterface.getParamReader().getStringRef("__query_col_name__").str().empty()) { + if (srvInterface.getParamReader().containsParameter("__query_col_idx__")) { + colInTable = (int)colInfo.getColumnCount() ; #if LOADER_DEBUG srvInterface.log("DEBUG __query_col_name__=<%s>",srvInterface.getParamReader().getStringRef("__query_col_name__").str().c_str()); srvInterface.log("DEBUG __query_col_idx__=<%s>",srvInterface.getParamReader().getStringRef("__query_col_idx__").str().c_str()); @@ -603,6 +605,9 @@ srvInterface.log("-----> External Table Columns, colInTable=<%d>", colInTable); query + " ) sq" ; } + } else { + // Plain COPY: column-filter param present but empty -> load all columns. + query = "SELECT * FROM ( " + query + " ) sq" ; } } else { @@ -665,6 +670,15 @@ srvInterface.log("-----> External Table Columns, colInTable=<%d>", colInTable); vtype = (BaseDataOID *)srvInterface.allocator->alloc(numcols * sizeof(BaseDataOID)) ; stype = (uint32 *)srvInterface.allocator->alloc(numcols * sizeof(uint32)) ; + // Plain COPY leaves vidx empty. Default to identity mapping and set + // colInTable so the pre-null loop covers all columns. + if (vidx.empty()) { + for (SQLSMALLINT i = 0; i < numcols; i++) { + vidx.push_back(i); + } + colInTable = numcols; + } + // Set up column-data buffers // Bind to the columns in question for (SQLSMALLINT i = 0; i < numcols; i++) { diff --git a/tests/expected/copy_test.out b/tests/expected/copy_test.out index d564af8..899dded 100644 --- a/tests/expected/copy_test.out +++ b/tests/expected/copy_test.out @@ -1,5 +1,3 @@ -Timing is on. -Pager usage is off. Timing is off. SET CREATE TABLE