diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 31bad56e..a3d2f712 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ env: # PostgreSQL build from source. POSTGRESQL_SOURCE_TAG: 'REL_18_STABLE' - OPENSSL_VERSION: '3_5_5' + OPENSSL_VERSION: '3_5_6' PKGCONFIGLITE_VERSION: '0.28-1' WINFLEXBISON_VERSION: '2.5.24' WORKFLOW_VERSION_POSTGRESQL: '1' # increment to invalidate cache @@ -322,7 +322,7 @@ jobs: - name: Install WiX shell: cmd run: | - dotnet tool install --global wix + dotnet tool install --global wix --version "6.*" wix extension add --global WixToolset.UI.wixext/6.0.0 - name: Build psqlodbc ${{matrix.variant}} diff --git a/info.c b/info.c index 755baed7..23623442 100644 --- a/info.c +++ b/info.c @@ -4055,7 +4055,11 @@ PGAPI_PrimaryKeys(HSTMT hstmt, " AND ta.attnum operator(pg_catalog.=) i.indkey[ia.attnum-1]" " AND (NOT ta.attisdropped)" " AND (NOT ia.attisdropped)" - " AND ic.oid operator(pg_catalog.=) i.indexrelid" + " AND ic.oid operator(pg_catalog.=) i.indexrelid"); + if (PG_VERSION_GE(conn, 11.0)) + appendPQExpBufferStr(&tables_query, + " AND ia.attnum operator(pg_catalog.<=) i.indnkeyatts"); + appendPQExpBufferStr(&tables_query, " order by ia.attnum"); break; case 2: @@ -4075,8 +4079,12 @@ PGAPI_PrimaryKeys(HSTMT hstmt, " AND ta.attrelid operator(pg_catalog.=) i.indrelid" " AND ta.attnum operator(pg_catalog.=) i.indkey[ia.attnum-1]" " AND (NOT ta.attisdropped)" - " AND (NOT ia.attisdropped)" - " order by ia.attnum", eq_string, escTableName, eq_string, pkscm); + " AND (NOT ia.attisdropped)", eq_string, escTableName, eq_string, pkscm); + if (PG_VERSION_GE(conn, 11.0)) + appendPQExpBufferStr(&tables_query, + " AND ia.attnum operator(pg_catalog.<=) i.indnkeyatts"); + appendPQExpBufferStr(&tables_query, + " order by ia.attnum"); break; } if (PQExpBufferDataBroken(tables_query)) diff --git a/test/expected/primarykeys-include.out b/test/expected/primarykeys-include.out new file mode 100644 index 00000000..03d2769b --- /dev/null +++ b/test/expected/primarykeys-include.out @@ -0,0 +1,6 @@ +connected +Check SQLPrimaryKeys with INCLUDE columns +Result set: +contrib_regression public pk_include_test a 1 pk_include_test_pkey +contrib_regression public pk_include_test b 2 pk_include_test_pkey +disconnecting diff --git a/test/src/primarykeys-include-test.c b/test/src/primarykeys-include-test.c new file mode 100644 index 00000000..1ad704f8 --- /dev/null +++ b/test/src/primarykeys-include-test.c @@ -0,0 +1,65 @@ +/* + * Test that SQLPrimaryKeys excludes INCLUDE columns. + * + * A PRIMARY KEY with INCLUDE (PG 11+) should only return the actual + * key columns, not the included columns. + */ +#include +#include + +#include "common.h" + +int +main(int argc, char **argv) +{ + SQLRETURN rc; + HSTMT hstmt = SQL_NULL_HSTMT; + + test_connect(); + + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt); + CHECK_CONN_RESULT(rc, "failed to allocate stmt handle", conn); + + /* INCLUDE clause requires PG >= 11 */ + if (server_version_lt(conn, 11, 0)) + { + printf("Server version < 11, skipping INCLUDE test\n"); + test_disconnect(); + return 0; + } + + /* Create table with PK that has INCLUDE columns */ + rc = SQLExecDirect(hstmt, + (SQLCHAR *) "DROP TABLE IF EXISTS pk_include_test", SQL_NTS); + CHECK_STMT_RESULT(rc, "DROP TABLE failed", hstmt); + + rc = SQLExecDirect(hstmt, + (SQLCHAR *) "CREATE TABLE pk_include_test (a int, b int, c int, d int," + " CONSTRAINT pk_include_test_pkey PRIMARY KEY (a, b) INCLUDE (c, d))", + SQL_NTS); + CHECK_STMT_RESULT(rc, "CREATE TABLE failed", hstmt); + + rc = SQLFreeStmt(hstmt, SQL_CLOSE); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + + /* Call SQLPrimaryKeys - should return only a and b, not c or d */ + printf("Check SQLPrimaryKeys with INCLUDE columns\n"); + rc = SQLPrimaryKeys(hstmt, + NULL, 0, + (SQLCHAR *) "public", SQL_NTS, + (SQLCHAR *) "pk_include_test", SQL_NTS); + CHECK_STMT_RESULT(rc, "SQLPrimaryKeys failed", hstmt); + print_result(hstmt); + + rc = SQLFreeStmt(hstmt, SQL_CLOSE); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + + /* Clean up */ + rc = SQLExecDirect(hstmt, + (SQLCHAR *) "DROP TABLE pk_include_test", SQL_NTS); + CHECK_STMT_RESULT(rc, "DROP TABLE failed", hstmt); + + test_disconnect(); + + return 0; +} diff --git a/test/tests b/test/tests index ead21ea6..d7cbec08 100644 --- a/test/tests +++ b/test/tests @@ -57,4 +57,5 @@ TESTBINS = exe/connect-test \ exe/wchar-char-test \ exe/params-batch-exec-test \ exe/fetch-refcursors-test \ - exe/descrec-test + exe/descrec-test \ + exe/primarykeys-include-test