Explorar el Código

Fix Postgres introspection schema leak, test cleanup SQL, stale doc comment

PostgresDialect.introspect_schema queried information_schema by table name
only, so tables with the same name in other schemas on the server (for
example leftover test isolation schemas) leaked duplicate columns and
primary keys into the introspected shape. Both the column and primary-key
queries now filter on current_schema(), and the constraint join also
matches table_schema on both sides.

scripts/run-postgres-tests.sh attempted to clean leftover isolation
schemas with a DO block that nested the same bare dollar-quote tag inside
itself, so the statement never parsed and silently did nothing; the regex
also expected names with two underscore groups while TestBackendContext
creates t_<n>. The block now uses distinct dollar-quote tags, format(%I)
for identifier quoting, and the correct regex. Validated against a live
server: 40 stale schemas were dropped.

Also removes an orphaned duplicate doc comment left behind in SqlDialect
for migrations_history_table_sql.
clanker hace 1 mes
padre
commit
e21354827f

+ 5 - 1
scripts/run-postgres-tests.sh

@@ -25,7 +25,11 @@ export PG_TEST_CONN="${PG_TEST_CONN:-postgresql://postgres@/sqltest?host=/tmp/pg
 # by the dual-backend ORM/migration/projection suites. Harmless when none
 # exist or when psql is unavailable.
 if command -v psql >/dev/null 2>&1; then
-    psql -h "${PGHOST:-/tmp/pgrun}" -p "${PGPORT:-5433}" -U "${PGUSER:-postgres}" -d "${PGDATABASE:-sqltest}" -c 'DROP SCHEMA IF EXISTS t_schema_cleanup_dummy CASCADE; DO $$ DECLARE r record; BEGIN FOR r IN SELECT nspname FROM pg_namespace WHERE nspname ~ $$^t_[0-9]+_[0-9]+$$ LOOP EXECUTE $$DROP SCHEMA IF EXISTS $$ || quote_ident(r.nspname) || $$ CASCADE$$; END LOOP; END $$;' >/dev/null 2>&1 || true
+    # Distinct dollar-quote tags are required: nesting the same bare $$ tag
+    # inside the DO body terminates the outer string early and the statement
+    # silently never runs. The regex matches the t_<n> names TestBackendContext
+    # actually creates (t_1, t_2, ...).
+    psql -h "${PGHOST:-/tmp/pgrun}" -p "${PGPORT:-5433}" -U "${PGUSER:-postgres}" -d "${PGDATABASE:-sqltest}" -c 'DO $cleanup$ DECLARE r record; BEGIN FOR r IN SELECT nspname FROM pg_namespace WHERE nspname ~ $regex$^t_[0-9]+$$regex$ LOOP EXECUTE format($drop$DROP SCHEMA IF EXISTS %I CASCADE$drop$, r.nspname); END LOOP; END $cleanup$;' >/dev/null 2>&1 || true
 fi
 
 # Meson may pass the test executable as a build-dir-relative path; the

+ 7 - 1
src/dialects/postgres-dialect.vala

@@ -503,7 +503,11 @@ namespace InvercargillSql.Dialects {
             var columns_sql = new StringBuilder();
             columns_sql.append("SELECT column_name, data_type, is_nullable, column_default, is_identity ");
             columns_sql.append("FROM information_schema.columns ");
-            columns_sql.append("WHERE table_name = :table_name ");
+            // Restrict to the first schema on the search path: tables with
+            // the same name in other schemas (e.g. leftover test schemas)
+            // must not leak duplicate columns into the introspected shape.
+            columns_sql.append("WHERE table_schema = current_schema() ");
+            columns_sql.append("  AND table_name = :table_name ");
             columns_sql.append("ORDER BY ordinal_position");
             var command = connection.create_command(columns_sql.str);
             command.with_parameter<string>("table_name", table_name);
@@ -559,7 +563,9 @@ namespace InvercargillSql.Dialects {
             pk_sql.append("JOIN information_schema.key_column_usage kcu ");
             pk_sql.append("  ON tc.constraint_name = kcu.constraint_name ");
             pk_sql.append(" AND tc.table_name = kcu.table_name ");
+            pk_sql.append(" AND tc.table_schema = kcu.table_schema ");
             pk_sql.append("WHERE tc.constraint_type = 'PRIMARY KEY' ");
+            pk_sql.append("  AND tc.table_schema = current_schema() ");
             pk_sql.append("  AND tc.table_name = :table_name ");
             pk_sql.append("ORDER BY kcu.ordinal_position");
             var pk_command = connection.create_command(pk_sql.str);

+ 0 - 12
src/dialects/sql-dialect.vala

@@ -254,18 +254,6 @@ namespace InvercargillSql.Dialects {
             """;
         }
         
-        /**
-         * Builds the CREATE TABLE statement for the migration history table.
-         * 
-         * MigrationRunner persists applied migrations in a table named
-         * __migrations. The column set is backend-independent, but the
-         * auto-increment syntax is not (SQLite uses INTEGER PRIMARY KEY
-         * AUTOINCREMENT, PostgreSQL uses GENERATED ALWAYS AS IDENTITY), so
-         * the DDL is provided by the dialect.
-         * 
-         * @return The CREATE TABLE IF NOT EXISTS statement for __migrations
-         */
-        
         /**
          * Generates a table alias with type information for debugging.
          *