Paritas In development
An Oracle-compatible PostgreSQL, built around one honest promise: we can tell you exactly where compatibility ends (for your code, with measured evidence) and close the gaps that matter to you.
Paritas is PostgreSQL 18 with an Oracle mode that compiles and runs real PL/SQL: packages, triggers, collections and exceptions. It is working toward 1.0 against eight published acceptance criteria, and every figure on this page comes from a dated run against Oracle Database 21c.
Paritas is not for sale yet: 1.0 has not shipped, and it ships only when all eight criteria hold. The test harness behind it already runs, and we are happy to show it live.
The dangerous half of a migration is invisible
When a company moves off Oracle, everyone focuses on converting the code, the visible half. The invisible half is that PostgreSQL is not Oracle: in places it computes a different answer to the same expression. Not an error. A different number.
Same code, different answers
Three real results, each measured on live engines. Every one converts cleanly, and none raises an error you would see at build time.
| Code | Oracle | PostgreSQL | Paritas |
|---|---|---|---|
SELECT 3.4e38f * 10fbinary floats multiplied past the top of the type | inf | an error: the literal is refused, and the nearest equivalent raises value out of range | inf ✓ |
SELECT 1 UNION SELECT 2 INTERSECT SELECT 2set operators without parentheses | 2 | 1, 2: INTERSECT binds tighter, so other rows come back | 2 ✓ |
FOR i IN REVERSE 1 .. 3 LOOPa loop that walks backwards | runs 3, 2, 1 | runs no iteration at all: its REVERSE takes the bounds the other way round | runs 3, 2, 1 ✓ |
A loop that walks a collection backwards silently does nothing; a report built on a set query silently gains rows. Paritas gives Oracle's answer in each case because we measured the difference rather than guessing at it. The first fix has since been taken into the upstream open-source project.
We built the test harness before the database
The moat is not the database. Anyone can fork one. It's a differential test harness: Oracle Database 21c, stock PostgreSQL and the unmodified open-source base Paritas is built on, all running beside Paritas. The same code goes to each engine and every answer is compared against Oracle's. A difference is only real once it is measured on a live engine, never assumed from a manual: on 9 October 2026 two fixes written from Oracle's own manual gave the wrong answer on a real Oracle 21c.
The differential corpus
762 cases of SQL and PL/SQL, each with the answer a real Oracle instance returned. Every engine runs every case, and every verdict is kept from run to run, so a change that fixes one answer and breaks another shows up in the next run.
The application gauntlet
591 units and 92,000 lines of real PL/SQL from nine schemas, among them the Alexandria, Logger, utPLSQL and PL/JSON libraries and Oracle's HR and OE samples, compiled unchanged. It ranks what breaks, so the most common blocker is fixed first.
Stress and sanitizer
170 stress cases, an AddressSanitizer build in continuous integration, and a 24-hour soak with flat memory on the release candidate. A database that gives Oracle's answers and then falls over is not compatible.
Eight criteria, each one a measurement
The bar for 1.0 was set in advance, as numbers rather than adjectives. Here is where each stood on 12 October 2026 (the call-site count is from 8 October).
| Criterion | 1.0 needs | Now |
|---|---|---|
| Real Oracle PL/SQL compiles unchanged | 90% of the gauntlet's 253 package-level units that Oracle itself compiles | 141 (56%) |
| Answers match Oracle | 95% of the 762 corpus cases | 593 (78%); the unmodified base gives 514 (67%) |
| It survives | no crash, sanitizer clean, a 24-hour soak with flat memory | no crash in 170 stress cases and sanitizer clean; five known crash cases still open, and the soak runs last |
| The built-in packages applications call exist | 70% of 2,994 call sites | 1,436 (48%) |
Errors behave like Oracle (the codes handlers catch, SQLCODE, SQLERRM, RAISE_APPLICATION_ERROR) | all 38 cases | 31 |
| Limitations listed honestly | a published list | written, and kept current |
| Maintainable from the documents alone | CI, the gate and the runbooks, each procedure rehearsed once from its runbook | CI and the gate run; three scripts, two runbooks and the rehearsals to go |
| A release exists | a 1.0.0-rc1 tag and changelog, reproducible from a clean clone | not yet |
The gauntlet holds 316 package-level units; 63 of them do not compile on Oracle 21c either, and code Oracle refuses measures nothing. About 760 of the 2,994 call sites are in packages left out of 1.0 by decision (below), so the most that criterion can reach in 1.0 is about 75%.
The Oracle that real code is written in
Each item below is tested against Oracle 21c's measured answers, and most arrived in the last few weeks because the gauntlet ranked them first.
Packages
- Specification and body, with state kept per session
- Package records, constants, cursors and initialization sections
- Types, subtypes and exceptions declared in a package and used from other code
- Private body items, and recursion that keeps each caller's values
The PL/SQL language
SUBTYPE, and 13 predefined subtypes such asPOSITIVEandNATURALPLS_INTEGER,SIMPLE_INTEGER,SYS_REFCURSORand cursor attributesSELECT INTO,EXECUTE IMMEDIATE, and procedure calls withoutCALLFOR ... IN REVERSEin Oracle's order
Exceptions
- User-defined and predefined exceptions, raised and caught by name
PRAGMA EXCEPTION_INITwith Oracle's scope and codesRAISE_APPLICATION_ERROR, andSQLCODEandSQLERRMin handlers
Collections and types
- Nested tables,
VARRAYandINDEX BY PLS_INTEGERcollections, withEXTEND BULK COLLECT,TABLE()in a query, and pipelined functions- Schema-level object types (attributes) and collection types, with constructors
Triggers and SQL
- Oracle's trigger syntax: the body in the statement,
:newand:old,INSERTING,UPDATING,DELETING,REFERENCING MINUS, Oracle's set-operator order, andROWNUMin single-table queries- IEEE arithmetic for
BINARY_FLOATandBINARY_DOUBLE DBMS_OUTPUT,DBMS_LOB,UTL_RAWand part ofDBMS_UTILITY
Running it
- One server, two dialects: Oracle mode on its own port beside PostgreSQL's, so no session has to switch
- Backup and restore of Oracle-mode databases with
pg_dump - Builds on Linux and on Windows, where three Oracle-mode tests still fail
Knowing the limits is the product
Any architect will test a compatibility claim within an hour. Say "Oracle compatible" without limits and you lose the account the moment they find the first gap. So we write down where it ends: our list of limitations runs to more than 140 entries, each saying what happens, and most what to do instead. The headlines are below.
Left out of 1.0, by decision
- Object types with methods: type bodies, member functions,
UNDER,REF - Autonomous transactions: refused when the code compiles, because a fake would be a trap
- The network packages (
UTL_HTTP,UTL_TCP,UTL_SMTP,UTL_MAIL) - The XML packages (
DBMS_XMLGEN,DBMS_XMLDOM,DBMS_XMLPARSER) DBMS_SCHEDULERandDBMS_JOB- Optimizer hints, which are read as comments
Open today
- Integer division truncates:
SELECT 10/4is2, where Oracle, which has no integer type, gives2.5 - A number turned into text keeps its leading zero:
TO_CHAR(0.5)is0.5, where Oracle gives.5 INDEX BY VARCHAR2collections andFORALLROWNUMin joins and in the nested pagination idiom;FETCH FIRSTworks- The
(+)outer join, which pgrecon rewrites toLEFT JOIN DBMS_SQL,UTL_FILEand four more packages, planned for 1.0
It plugs straight into pgrecon
pgrecon tells you what your Oracle estate contains and what a migration will cost. The Paritas harness tells you which of that estate behaves differently on the destination (measured, per expression). The two already share their plumbing: the tables the gauntlet compiles real PL/SQL against are extracted and converted by pgrecon itself. Know the scope, then know the risk, before you commit.
What exists today
We would rather you hear the limits now than in six months.
Built and working
- The harness: the corpus, the gauntlet and the stress suite, with a dated run behind every figure here
- Paritas builds, installs and runs as PostgreSQL 18 with an Oracle mode, fully rebranded
- Every change passes a gate (a build with zero warnings and the full regression suites) and independent review
- Every expected answer in its tests is Oracle 21c's, measured, never copied from a manual
Upstream, done right
Paritas builds on Apache-2.0-licensed open-source technology, so it is fully legal, with proper attribution files. Where we find a defect that belongs upstream, we send it back with a reproduction the maintainers can run, building credibility in the PostgreSQL world rather than maintaining a private fork of everything.
It is working: the floating-point fix above was merged into the upstream open-source project on 3 September 2026. Since then we have filed eleven more issue reports with reproductions and opened ten pull requests with fixes, all still under review on 13 October 2026. Paritas carries its own fix for each of those pull requests meanwhile, and drops it when upstream's version arrives.
Still to come before 1.0
- 87 more real units compiling, and 131 more corpus answers matching Oracle
- The five known crash cases, then the 24-hour soak
DBMS_SQL,UTL_FILE,DBMS_ASSERT,DBMS_RANDOM,DBMS_APPLICATION_INFOandDBMS_CRYPTO- The release runbooks, and a
1.0.0-rc1tag
Paritas cannot be bought today, and we give no date: 1.0 ships when the eight criteria hold, not before.
Moving off Oracle? Let's measure the risk
We can show you the harness running (it's more convincing to watch than to describe) and tell you exactly where compatibility ends for your code.