Skip to content

Releases: Levyks/dbsaci

v0.0.8

Choose a tag to compare

@Levyks Levyks released this 03 Sep 14:43

Session time zones, done the way Oracle does them.

What changed

  • ALTER SESSION SET TIME_ZONE accepts a named IANA region
    ('America/Sao_Paulo'), a fixed offset ('-03:00'), or 'local'.
  • TIMESTAMPTZ values are converted to the session zone on the wire — with
    per-instant, DST-correct offsets for named regions — instead of coming back in
    UTC. Views no longer need AT TIME ZONE / ::timestamp casts, and the Oracle
    JDBC thin driver no longer needs oracle.jdbc.timezoneAsRegion=false. PG
    timestamp (no zone) is unchanged.
  • SESSIONTIMEZONE, DBTIMEZONE (usable without parens),
    SYS_CONTEXT('USERENV','SESSIONTIMEZONE' | 'DB_TIMEZONE').
  • Preflight also drops a stale oracle.sys_context left by pre-0.0.5 builds,
    which shadowed the current public.sys_context.

Note

New chrono-tz dependency bundles the IANA time-zone database (pure Rust). The
image stays a static musl binary on scratch, now ~12 MB (was ~10).

New corpus group time_zones.sql (13 cases). corpus 664 → 675.

docker pull levyks/pgsaci:0.0.8

v0.0.7

Choose a tag to compare

@Levyks Levyks released this 03 Sep 14:18

Acting on an external review of pgSaci's drop-in experience.

Added

  • Preflight diagnostics. On its first backend connection pgSaci logs a
    one-time check of the target database: is orafce installed, what is the
    effective search_path, and does the login user's schema contain any
    upper/mixed-case identifiers an Oracle client can't reach. A missing
    assumption now shows up as one line, not an opaque PostgreSQL error later.
  • Session visibility. GET /sessions on the health port returns a JSON
    list of live Oracle sessions (id, addr, user, age_seconds);
    DELETE /sessions/<id> aborts one — dropping its backend PostgreSQL
    connection and releasing any locks it held.
  • Idle-reap timeout is logged at startup (default unchanged at 900s).
  • Docs: Identifier case (use lower-case identifiers in the target schema),
    Oracle JDBC thin driver (oracle.jdbc.timezoneAsRegion=false), and
    Preflight diagnostics sections in getting-started.

Deliberately not done

  • No distinctive "unsupported construct" error — pgSaci stays a best-effort
    text rewriter.
  • No case-insensitive catalog identifier resolution — conflicts with the
    stateless text-rewriter design and with Oracle semantics where "no"/"NO"
    coexist; the preflight warning covers the real pain.
  • No timestamptz -> DATE wire mode / TZ-region negotiation yet — touches
    result encoding and drops tz precision; documented the workaround instead.

docker pull levyks/pgsaci:0.0.7 — digest sha256:6357a2787e75…, 9.77 MB.

v0.0.6

Choose a tag to compare

@Levyks Levyks released this 02 Sep 18:57

IDE schema browser: fill out the ALL_* data dictionary

DataGrip / IntelliJ (and SQL Developer, DBeaver) introspect a long tail of
Oracle dictionary views and abort on the first missing view or column. This
release widens the ones they read column-by-column and stubs the rest.

  • ALL_TABLES / ALL_INDEXES / ALL_TRIGGERS (and their USER_* views)
    grow the full Oracle column set, appended so CREATE OR REPLACE VIEW accepts
    it. ALL_TRIGGERS now derives real timing / event / BEFORE_ROW etc. from
    pg_trigger.tgtype and carries ACTION_TYPE.
  • New: SYS.ALL_OBJECT_TABLES, ALL_MVIEW_LOGS, ALL_MVIEW_COMMENTS,
    ALL_IND_EXPRESSIONS.
  • ~45 new SYS.* stub views — partitioning / subpartitions, object types /
    collections / methods, LOBs, ALL_TAB_IDENTITY_COLS (real, from
    pg_attribute.attidentity), privileges, tablespaces / segments, scheduler /
    jobs / queues, directories / libraries / java / clusters / operators /
    indextypes, XML DB, editions, VPD policies, dimensions, optimizer stats &
    histograms, PL/SQL settings, identifiers. Empty (no PostgreSQL equivalent) —
    the point is only that a SELECT resolves instead of ORA-00942 / ORA-00904.
  • Version / identity: SYS.PRODUCT_COMPONENT_VERSION,
    NLS_DATABASE_PARAMETERS, DATABASE_PROPERTIES, GLOBAL_NAME — plus
    unqualified copies of the first three.

Known gap: SYS.ALL_SOURCE resolves but returns nothing.

docker pull levyks/pgsaci:0.0.6 — digest sha256:5108c80e80d8…, 9.77 MB.

v0.0.5

Choose a tag to compare

@Levyks Levyks released this 02 Sep 04:39

Schema == user

Every pgSaci user now owns a PostgreSQL schema of its own name, instead of its
objects landing in the shared oracle schema by search_path accident. The
catalog facade stops faking owners — an IDE shows your tables under your node
because the schema genuinely is yours.

  • Connect: CREATE SCHEMA IF NOT EXISTS "<user>" (best-effort — a backend
    role without CREATE on the database still connects; objects then resolve via
    oracle / public and a warning is logged). search_path = "<user>", oracle, public.
  • public is the shared fallback: unqualified names not in your schema
    resolve there, and public.<name> always works — front an existing
    PostgreSQL database whose tables live in public and it works unchanged.
  • Cross-schema access is a qualified name plus grants
    (SELECT * FROM hr.emp); ALTER SESSION SET CURRENT_SCHEMA = hr redirects
    unqualified resolution.
  • Facade reverts the 0.0.4 oracle → current_user workaround — owners and
    USER_* scoping are honest again.

New corpus group schemas.sql (11 cases). corpus 644 → 655.

docker pull levyks/pgsaci:0.0.5

v0.0.4

Choose a tag to compare

@Levyks Levyks released this 01 Sep 04:38

IDE schema browser: objects appear under the connected user

pgSaci keeps every user's objects in a shared PostgreSQL oracle schema. The
SYS.ALL_* / USER_* catalog facade was exposing that literally as owner
ORACLE, and sys.all_users never listed the login role — so DataGrip /
IntelliJ (which assume Oracle's "schema == user" model) showed no node for the
connected user and none of their tables.

  • all_* / user_* facade views now report objects in the oracle schema as
    owned by current_user; user_* filters follow the same mapping.
  • sys.all_users lists the connected user; the per-package schemas orafce
    creates (dbms_*, plv*, utl_file, plunit) are filtered out.
  • PostgreSQL 18 catalogues NOT NULL as pg_constraint.contype = 'n' — mapped
    to Oracle constraint_type = 'C' with a NOT NULL <col> search condition
    instead of leaking the raw 'n'.
  • dbms_metadata.get_ddl(type, name, schema): when schema is the connected
    user, resolve against the oracle schema.

Also in this line: CONNECT BY on NUMBER(p)-typed key columns (v0.0.3) —
the WITH RECURSIVE ancestor-path array had a typmod mismatch between the
union arms, breaking any hierarchy keyed on a precision-qualified NUMBER.

docker pull levyks/pgsaci:0.0.4 — digest sha256:5ffd5c107452…, 9.77 MB.

v0.0.3

Choose a tag to compare

@Levyks Levyks released this 01 Sep 04:10

Fixes

  • CONNECT BY on NUMBER(p)-typed key columns now translates. The
    CONNECT BY → WITH RECURSIVE lowering carries an ancestor-id path array for
    cycle detection; the non-recursive arm kept the key column's typmod
    (numeric(4,0)[]) while the recursive arm produced numeric[], and
    PostgreSQL rejects a recursive union whose arms disagree on type. Any
    hierarchy keyed on a precision-qualified NUMBER — i.e. most real Oracle
    HR/ERP schemas — failed with
    recursive query "__cb" column N has type numeric(4,0)[] .... Path-array
    elements are now normalised to text in both arms. (5ba1bba)

Benchmarks

  • bench/run.sh now runs entirely in Docker on one bridge network (client,
    Oracle XE, PostgreSQL, pgSaci), pgSaci from the published image, both engines
    at 2 CPU / 2.5 GiB with Oracle spending its full 2 GiB licence and PostgreSQL
    tuned to the envelope. Refreshed numbers in the README and docs. (f50f426)

Docker

docker pull levyks/pgsaci:0.0.3 — digest sha256:1217905bd2aa…, 9.77 MB
(static musl on scratch).

pgSaci 0.0.2

Choose a tag to compare

@Levyks Levyks released this 31 Aug 23:45

Alpha. Very early — do not point it at data you care about.

Container

docker pull levyks/pgsaci:0.0.2

~10 MB static-musl image on scratch. See the docs.

Since 0.0.1 — IDE schema-browser compatibility

DataGrip / IntelliJ (the reference client) now introspects a pgSaci connection end to end and can browse and query the schema tree.

  • SYS.ALL_* / SYS.USER_* data-dictionary facade over pg_catalog — tables, columns, objects, constraints, indexes, sequences, comments, triggers, users — returning UPPERCASE identifiers like a real Oracle database, so Oracle tooling stops seeing public and PUBLIC as two schemas.
  • DBMS_METADATA.GET_DDL (TABLE / VIEW / MATERIALIZED VIEW / INDEX / SEQUENCE / TRIGGER / FUNCTION) for the "copy DDL" action, rendered as PostgreSQL DDL. Plus DBMS_UTILITY.GET_HASH_VALUE, USER_TABLESPACES, sys.session_roles / session_privs.
  • DECODE now compares its operands as text — Oracle coerces them to one type; PostgreSQL's = does not, so DECODE(sys_context(...), 0, ...) no longer fails.
  • Translator: SELECT-list aliases now resolve inside ORDER BY expressions (ORDER BY decode(alias, ...)), matching Oracle.

Fixes

  • Connect-storm deadlock. The catalog facade (CREATE OR REPLACE VIEW, ACCESS EXCLUSIVE) was re-applied on every connect; an IDE client idle in a transaction would freeze a wave of new connections behind it. It's now applied once per deploy, guarded by a version marker and an advisory lock.

Verified

cargo test --lib 30/0 · --test corpus 638/0 · --test translate_golden · python-oracledb thin 31/31 · ODP.NET 13/13 · abstraction.mdc Spring/ojdbc suite 32/32.