seed-sql.sh ported to Oracle (CLOB credential + CONNECT BY)
- Condition
- The last engine-tooling gap: seed-sql.sh was postgres/mysql/mariadb only
What was done
bin/seed-sql.sh now supports oracle. Two Oracle-specific mechanics, both of
which are load-bearing rather than cosmetic:
- Row generation —
CONNECT BY LEVEL. Oracle has nogenerate_seriesand no recursive CTE (well, it has recursiveWITH, but the idiomatic generator isSELECT lo + LEVEL - 1 FROM dual CONNECT BY LEVEL <= (hi-lo+1)). - Credential copy — a PL/SQL block.
SECRET_DATA/CREDENTIAL_DATAareCLOBon Oracle (confirmed fromall_tab_columns; the changelog creates them as CLOB and only the fill SQL is Oracle-specific, because Oracle'sCONCATtakes exactly two args). A scalar subquery returning a CLOB is rejected (ORA-00932/ORA-22848), so the template credential is read into PL/SQLCLOBvariables withSELECT … INTOand then referenced by the INSERT — the value never crosses the shell boundary (important: the argon2secret_datacontains$argon2id$…).
Also engine-specific: EMAIL_VERIFIED/ENABLED are native BOOLEAN (insert
TRUE), USERNAME/FIRST_NAME/LAST_NAME/VALUE are NVARCHAR2,
CREATED_TIMESTAMP is NUMBER (ms epoch via ROUND((SYSDATE - DATE '1970-01-01') * 86400000)), and identifiers are UPPERCASE (shared with the
mysql/mariadb branch). Stats are gathered with DBMS_STATS.GATHER_TABLE_STATS
and the planner estimate is all_tables.num_rows; size is
user_segments.
Result (verified at 100 users, then extension + multi-batch + --no-analyze)
| Check | Value |
|---|---|
--users 100 | 100 users + 1 template; 100 creds; 200 attrs |
| credential CLOB copied | DBMS_LOB.COMPARE = 0 (match), secret_data length 116 |
--start extension | 50 appended users |
--batch 25 multi-batch | 2 batches clean |
--no-analyze | reports all_tables.num_rows (102, the pre-stats estimate) |
| clean run | 10 users in 2s, no sqlplus feedback noise |
Gotcha worth recording
The deterministic sql-<32-digit> ids are a table-wide primary key, not
per-realm. Seeding a second realm with the same --start/--users range
collides (ORA-00001 … ID already exists) — this is true on every engine, not
Oracle-specific, and is the reason --start exists. Re-running an overlapping
range is not idempotent; the script assumes each range is seeded once.
Verification
| Claim | Evidence |
|---|---|
| Oracle seeds 100 with correct shape | 100 users / 100 creds / 200 attrs ☑ |
| CLOB credential copied from template | DBMS_LOB.COMPARE = 0 ☑ |
| BOOLEAN + NVARCHAR2 + NUMBER columns accept the seed | rows inserted, no type errors ☑ |
| Extension / multi-batch / no-analyze paths work | 3 extra runs ☑ |