← SkillSafe / PL/SQL Shift

Your Oracle package, rewritten as PL/pgSQL you can actually read

Paste the package body — or a standalone procedure, a function, a trigger, whatever you have — and add the CREATE TABLE DDL if you want %TYPE anchors to resolve. You get the PostgreSQL translation with every signature preserved, a construct-by-construct map of what changed, and the parts PostgreSQL cannot do faithfully marked -- MANUAL: rather than quietly faked.

Both examples ship with a saved model run, so you can see the whole translation — including the SQL — without signing in and without spending a credit. One is an autonomous-transaction package that cannot be translated mechanically; the other is a clean pair of helpers where the only real question is collation.

nothing pasted yet
Drag .sql, .pks, .pkb or .prc files in, or Everything is read in your browser. Nothing uploads until you run.
no DDL pasted
Paste some PL/SQL to price the run.

What this does, and what it does not

The prescan is real parsing. String literals and comments are blanked before anything is matched, so a NVL mentioned inside a comment is not counted as code. Every CREATE and every nested PROCEDURE or FUNCTION is read into its name, its parameters, their IN / OUT / IN OUT modes and their %TYPE anchors, and the CREATE TABLE DDL you paste is parsed for column types. Every Oracle construct it finds is then classified by what the translation has to do about it: a mechanical substitution, a case orafce carries, a rewrite whose shape changes, or a blocker PostgreSQL has no faithful answer for. That last class is the one that decides a migration schedule — PRAGMA AUTONOMOUS_TRANSACTION, package-level session state, UTL_FILE, DBMS_LOCK — and it is the reason this page refuses to call a package "translated" when it is really "rewritten by someone who has not decided yet".

Several of the flags are semantic rather than lexical, which is where a grep would let you down: x = '' is a comparison that is always false in Oracle and sometimes true in PostgreSQL, ROWNUM is assigned before ORDER BY so a naive LIMIT returns different rows, SYSDATE - 7 is an error rather than a week, and an ORDER BY on a text column sorts differently under a linguistic collation than under Oracle's binary one unless it carries COLLATE "C".

Everything the prescan finds is handed to the model as facts it must reconcile, and the SQL that comes back is parsed again here: residual Oracle syntax is counted, routines that went missing are named, parameter names that moved are listed, and any secret the reply echoed out of your paste is flagged. It reads; it does not run anything, it never connects to a database, and it is not a substitute for running the output against a real schema — which is the command every translation here ends with. A credential you paste is a credential you should rotate.

Nothing to hand? Load , whose autonomous transaction and package variables have no PostgreSQL equivalent, or , which translate cleanly once you decide what sort order the report has to match. Both replay a saved run for free.