Summary
Every SQL statement VCell's database layer emits is exercised in CI only against PostgreSQL, and runs in production only against Oracle. The two are not the same statements: DbDriver and friends branch on DatabaseSyntax in 55 places across 33 files, and the Oracle side of every one of those branches is untested.
This came up while fixing #1992 (see #1993). That PR added Oracle coverage for one thing — the cleanup sweep — via a new Oracle_IT regression group. The same reasoning applies to the rest of the database layer, and it is now cheap enough to be worth doing.
Why this is a real gap, not a theoretical one
The dialect branches are not cosmetic. A sample:
MINUS vs EXCEPT in the unreferenced-row queries.
MathDescriptionDbDriver takes a completely different write path per dialect — updateCleanLOB on Oracle vs the PostgreSQL branch — so CLOB handling for math descriptions is only ever run one way in tests and the other way in production.
varchar2_CLOB_update and the LRG/SML column-splitting idiom throughout DbDriver.
Field.SQLDataType maps every column type per dialect; ImageDataTable, BrowseImageDataTable, CurveTable, MathModelTable all carry their own case ORACLE.
A defect on the Oracle side of any of these is invisible until it reaches production, which is exactly how #1992 and #1961 stayed open.
What it would take
Not a new profile name. The natural instinct is to add a dev2-style Quarkus profile, but AgroalConnectionFactory.usePostgresql() hardcodes a switch on quarkus.profile:
switch (activeProfile) {
case "test", "dev": return true; // postgres
case "prod": return false; // oracle
default: throw new IllegalStateException("Unexpected value: " + activeProfile);
}
A new profile name throws on that default until the switch learns it, and every future profile has to be added in two places. Better to key the datasource choice off its own config property (vcell.datasource=postgresql|oracle), leaving profiles orthogonal — the same test suite then runs under either database by flipping one property.
The schema is the cheap part. %test.quarkus.datasource.postgresql.devservices.init-script-path=scripts/init.sql points at a hand-maintained PostgreSQL script (79 CREATE TABLEs, bigint/text/numeric). No Oracle equivalent has to be written by hand: SQLCreateAllTables.getVCellTables() is public static, and Table.getCreateSQL(DatabaseSyntax) already emits per-dialect DDL. A test resource can build the Oracle schema directly from the table list. (Don't reuse SQLCreateAllTables.main — it opens a Swing JOptionPane confirmation, so it cannot run headless.)
The container. quarkus-jdbc-oracle and ojdbc11 are already vcell-rest dependencies, so nothing new is needed there. Quarkus devservices will not start one as things stand, because the Oracle datasource is declared quarkus.datasource.oracle.db-kind=other. Two options: change it to db-kind=oracle, or — probably better, since it leaves the production datasource block alone — add a QuarkusTestResourceLifecycleManager that starts gvenzl/oracle-free:23-slim-faststart and injects the JDBC URL. That is the pattern ArtemisTestResource already uses in this module, and #1993's DatabaseCleanupOracleSqlTest shows the image works: 55s from pull to a usable database on a GitHub runner, whole job 2m35s.
Where it should run
Not the fast lane — it roughly doubles the Quarkus suite (79 tests) and adds the image pull. It belongs beside Oracle_IT as a regression group, e.g. Quarkus_Oracle_IT, so the merge queue and the nightly gate it while every push stays fast.
Suggested order
- Replace the profile-name switch in
AgroalConnectionFactory with a datasource config property, defaulting to today's behaviour. No test changes.
- Add an Oracle
QuarkusTestResourceLifecycleManager that starts the container and builds the schema from getVCellTables() + getCreateSQL(ORACLE).
- Add the
Quarkus_Oracle_IT regression group running the existing suite with the property flipped, and fix whatever it turns up. Expect the first run to find things — that is the point.
Related: #1992, #1961, PR #1993.
Summary
Every SQL statement VCell's database layer emits is exercised in CI only against PostgreSQL, and runs in production only against Oracle. The two are not the same statements:
DbDriverand friends branch onDatabaseSyntaxin 55 places across 33 files, and the Oracle side of every one of those branches is untested.This came up while fixing #1992 (see #1993). That PR added Oracle coverage for one thing — the cleanup sweep — via a new
Oracle_ITregression group. The same reasoning applies to the rest of the database layer, and it is now cheap enough to be worth doing.Why this is a real gap, not a theoretical one
The dialect branches are not cosmetic. A sample:
MINUSvsEXCEPTin the unreferenced-row queries.MathDescriptionDbDrivertakes a completely different write path per dialect —updateCleanLOBon Oracle vs the PostgreSQL branch — so CLOB handling for math descriptions is only ever run one way in tests and the other way in production.varchar2_CLOB_updateand the LRG/SML column-splitting idiom throughoutDbDriver.Field.SQLDataTypemaps every column type per dialect;ImageDataTable,BrowseImageDataTable,CurveTable,MathModelTableall carry their owncase ORACLE.A defect on the Oracle side of any of these is invisible until it reaches production, which is exactly how #1992 and #1961 stayed open.
What it would take
Not a new profile name. The natural instinct is to add a
dev2-style Quarkus profile, butAgroalConnectionFactory.usePostgresql()hardcodes a switch onquarkus.profile:A new profile name throws on that
defaultuntil the switch learns it, and every future profile has to be added in two places. Better to key the datasource choice off its own config property (vcell.datasource=postgresql|oracle), leaving profiles orthogonal — the same test suite then runs under either database by flipping one property.The schema is the cheap part.
%test.quarkus.datasource.postgresql.devservices.init-script-path=scripts/init.sqlpoints at a hand-maintained PostgreSQL script (79CREATE TABLEs,bigint/text/numeric). No Oracle equivalent has to be written by hand:SQLCreateAllTables.getVCellTables()ispublic static, andTable.getCreateSQL(DatabaseSyntax)already emits per-dialect DDL. A test resource can build the Oracle schema directly from the table list. (Don't reuseSQLCreateAllTables.main— it opens a SwingJOptionPaneconfirmation, so it cannot run headless.)The container.
quarkus-jdbc-oracleandojdbc11are already vcell-rest dependencies, so nothing new is needed there. Quarkus devservices will not start one as things stand, because the Oracle datasource is declaredquarkus.datasource.oracle.db-kind=other. Two options: change it todb-kind=oracle, or — probably better, since it leaves the production datasource block alone — add aQuarkusTestResourceLifecycleManagerthat startsgvenzl/oracle-free:23-slim-faststartand injects the JDBC URL. That is the patternArtemisTestResourcealready uses in this module, and #1993'sDatabaseCleanupOracleSqlTestshows the image works: 55s from pull to a usable database on a GitHub runner, whole job 2m35s.Where it should run
Not the fast lane — it roughly doubles the Quarkus suite (79 tests) and adds the image pull. It belongs beside
Oracle_ITas a regression group, e.g.Quarkus_Oracle_IT, so the merge queue and the nightly gate it while every push stays fast.Suggested order
AgroalConnectionFactorywith a datasource config property, defaulting to today's behaviour. No test changes.QuarkusTestResourceLifecycleManagerthat starts the container and builds the schema fromgetVCellTables()+getCreateSQL(ORACLE).Quarkus_Oracle_ITregression group running the existing suite with the property flipped, and fix whatever it turns up. Expect the first run to find things — that is the point.Related: #1992, #1961, PR #1993.