diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 875732cde..37c8b1aaa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -72,6 +72,20 @@ jobs: --health-timeout 5s --health-retries 5 + postgres15: + image: postgres:15 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: nette_test + ports: + - 5434:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + mssql: image: mcr.microsoft.com/mssql/server:latest env: diff --git a/src/Database/Drivers/PgSqlDriver.php b/src/Database/Drivers/PgSqlDriver.php index deb3e927e..ec23f84e1 100644 --- a/src/Database/Drivers/PgSqlDriver.php +++ b/src/Database/Drivers/PgSqlDriver.php @@ -148,11 +148,11 @@ public function getColumns(string $table): array ELSE NULL END AS size, NOT (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS nullable, - pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass)::varchar AS default, + pg_catalog.pg_get_expr(ad.adbin, ad.adrelid)::varchar AS default, coalesce(co.contype = 'p' AND (seq.relname IS NOT NULL OR strpos(pg_catalog.pg_get_expr(ad.adbin, ad.adrelid), 'nextval') = 1), FALSE) AS autoincrement, coalesce(co.contype = 'p', FALSE) AS primary, coalesce(col_description(c.oid, a.attnum)::varchar, '') AS comment, - coalesce(seq.relname, substring(pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass) from 'nextval[(]''"?([^''"]+)')) AS sequence + coalesce(seq.relname, substring(pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) from 'nextval[(]''"?([^''"]+)')) AS sequence FROM pg_catalog.pg_attribute AS a JOIN pg_catalog.pg_class AS c ON a.attrelid = c.oid diff --git a/tests/Database/Reflection.postgre.phpt b/tests/Database/Reflection.postgre.phpt index b3788e82a..cbdde4f6b 100644 --- a/tests/Database/Reflection.postgre.phpt +++ b/tests/Database/Reflection.postgre.phpt @@ -76,3 +76,32 @@ test('Tables in schema', function () use ($connection) { $connection->query('SET search_path TO one, two'); Assert::same(['one_slave_fk', 'one_two_fk'], names($driver->getForeignKeys('slave'))); }); + + +test('Table with GENERATED ALWAYS AS stored columns', function () use ($connection) { + $ver = $connection->query('SHOW server_version')->fetchField(); + if (version_compare($ver, '12') < 0) { + Tester\Environment::skip("GENERATED ALWAYS AS requires PostgreSQL 12+, running $ver."); + } + + Nette\Database\Helpers::loadFromFile($connection, Tester\FileMock::create(' + DROP TABLE IF EXISTS "generated_test"; + + CREATE TABLE "generated_test" ( + "id" serial PRIMARY KEY, + "first_name" varchar(50) NOT NULL, + "last_name" varchar(50) NOT NULL, + "full_name" text GENERATED ALWAYS AS ("first_name" || \' \' || "last_name") STORED + ); + ')); + + $driver = $connection->getDriver(); + $columns = $driver->getColumns('generated_test'); + $columnNames = array_column($columns, 'name'); + + Assert::same(['id', 'first_name', 'last_name', 'full_name'], $columnNames); + + $fullNameCol = $columns[3]; + Assert::same('full_name', $fullNameCol['name']); + Assert::same('TEXT', $fullNameCol['nativetype']); +}); diff --git a/tests/databases.github.ini b/tests/databases.github.ini index d00f44271..ba5deb2c8 100644 --- a/tests/databases.github.ini +++ b/tests/databases.github.ini @@ -24,6 +24,12 @@ username = postgres password = postgres options[newDateTime] = yes +[postgresql 15] +dsn = "pgsql:host=127.0.0.1;port=5434;dbname=nette_test" +username = postgres +password = postgres +options[newDateTime] = yes + [sqlsrv] dsn = "sqlsrv:Server=localhost,1433;Database=nette_test" username = SA