FOR var IN (SELECT ...) | Implicit RECORD declaration for FOR loop cursor variables | ❌ | ❌ | ✅ | #983 Open |
EXCEPTION type | User-defined exception types with RAISE/WHEN support | ❌ | ❌ | ✅ | #972Merged |
ROWNUM | Oracle row numbering pseudocolumn | ❌ | ❌ | ✅ | #1000 Open |
ROWID (automatic) | Physical row address on all tables | ❌ | ❌ | ❌ | N/A |
ROWID (opt-in) | Physical row address with explicit option | ❌ | ⚠️ | ⚠️ | Implemented |
DBMS_OUTPUT.PUT_LINE() | Output text with newline to buffer | ❌ | ❌ | ✅ | #998 Open |
DBMS_OUTPUT.PUT() | Output text without newline to buffer | ❌ | ❌ | ⚠️ | #998 Open |
DBMS_OUTPUT.ENABLE() | Enable output buffer | ❌ | ❌ | ⚠️ | #998 Open |
DBMS_OUTPUT.NEW_LINE() | Output newline character | ❌ | ❌ | ⚠️ | #998 Open |
DBMS_OUTPUT.DISABLE() | Disable output buffer | ❌ | ❌ | ⚠️ | #998 Open |
DBMS_UTILITY.FORMAT_CALL_STACK() | Returns current call stack | ❌ | ❌ | ✅ | #1001 Open |
DBMS_UTILITY.FORMAT_ERROR_STACK() | Returns error message | ❌ | ❌ | ✅ | #1001 Open |
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE() | Returns call stack where exception was raised | ❌ | ❌ | ✅ | #1001 Open |
PACKAGE / PACKAGE BODY | Package specification and body structure | ❌ | ✅ | ✅ | Implemented |
PRAGMA AUTONOMOUS_TRANSACTION | Independent transactions that commit separately | ❌ | ❌ | ✅ | #986 Open |
SYS_CONTEXT('USERENV', 'CURRENT_USER') | Current database username | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'SESSION_USER') | Session username | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'IP_ADDRESS') | Client IP address | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'SID') | Session identifier | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'SESSIONID') | Session sequence number | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'DB_NAME') | Database name | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') | Current schema name | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'LANG') | Language setting | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('USERENV', 'ISDBA') | User is superuser | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('SYS_SESSION_ROLES', 'DBA') | User has DBA role | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('SYS_SESSION_ROLES', 'LOGIN') | User has login privilege | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('SYS_SESSION_ROLES', 'CREATEROLE') | User can create roles | ❌ | ✅ | ✅ | Implemented |
SYS_CONTEXT('SYS_SESSION_ROLES', 'CREATEDB') | User can create databases | ❌ | ✅ | ✅ | Implemented |
DECODE(expr, search, result, ...) | Inline conditional logic | ❌ | ✅ | ✅ | Implemented |
ADD_MONTHS(date, n) | Add months to date | ❌ | ✅ | ✅ | Implemented |
LAST_DAY(date) | Last day of month | ❌ | ✅ | ✅ | Implemented |
NEXT_DAY(date, weekday) | Next specified weekday | ❌ | ✅ | ✅ | Implemented |
%TYPE | Variable type inheritance from table columns | ✅ | ✅ | ✅ | Implemented |
VARCHAR2 type | Oracle variable-length string type | ❌ | ✅ | ✅ | Implemented |
NUMBER type | Oracle numeric type | ❌ | ✅ | ✅ | Implemented |
DATE type | Oracle date/time type | ⚠️ | ✅ | ✅ | Implemented |
v$mystat / v$statname | Oracle session statistics views | ❌ | ❌ #1003 | ❌ | Not started |
IDENTIFIER# | Oracle # character in unquoted identifiers | ❌ | ❌ #1002 | ❌ | Not started |
CONNECT BY | Hierarchical queries with LEVEL pseudocolumn | ❌ | ❌ | ❌ | Not started |
Overview
Comprehensive Oracle PL/SQL compatibility analysis based on direct feature testing.
Test Images:
ivorysql/ivorysql:5.0-bookwormrophy/ivorysql:20251204-ab4128aCompatibility Matrix
FOR var IN (SELECT ...)EXCEPTIONtypeROWNUMROWID(automatic)ROWID(opt-in)DBMS_OUTPUT.PUT_LINE()DBMS_OUTPUT.PUT()DBMS_OUTPUT.ENABLE()DBMS_OUTPUT.NEW_LINE()DBMS_OUTPUT.DISABLE()DBMS_UTILITY.FORMAT_CALL_STACK()DBMS_UTILITY.FORMAT_ERROR_STACK()DBMS_UTILITY.FORMAT_ERROR_BACKTRACE()PACKAGE/PACKAGE BODYPRAGMA AUTONOMOUS_TRANSACTIONSYS_CONTEXT('USERENV', 'CURRENT_USER')SYS_CONTEXT('USERENV', 'SESSION_USER')SYS_CONTEXT('USERENV', 'IP_ADDRESS')SYS_CONTEXT('USERENV', 'SID')SYS_CONTEXT('USERENV', 'SESSIONID')SYS_CONTEXT('USERENV', 'DB_NAME')SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA')SYS_CONTEXT('USERENV', 'LANG')SYS_CONTEXT('USERENV', 'ISDBA')SYS_CONTEXT('SYS_SESSION_ROLES', 'DBA')SYS_CONTEXT('SYS_SESSION_ROLES', 'LOGIN')SYS_CONTEXT('SYS_SESSION_ROLES', 'CREATEROLE')SYS_CONTEXT('SYS_SESSION_ROLES', 'CREATEDB')DECODE(expr, search, result, ...)ADD_MONTHS(date, n)LAST_DAY(date)NEXT_DAY(date, weekday)%TYPEVARCHAR2typeNUMBERtypeDATEtypev$mystat/v$statnameIDENTIFIER##character in unquoted identifiersCONNECT BYLegend:
Summary
WITH (rowid=on)CONNECT BY- hierarchical queriesROWID(automatic) - not available without opt-inv$mystat/v$statname- session statistics views (#1003)#in identifiers - column names likeSTATISTIC#(#1002)Pending Upstream PRs
The following features from rophy/IvorySQL have open PRs pending review:
Upstream vs Fork Comparison
Features added in rophy/IvorySQL fork (not in upstream
ivorysql/ivorysql:5.0-bookworm):ROWNUM"rownum": invalid identifierFOR cr IN (SELECT...)loop variable must be a record variableDBMS_OUTPUT.PUT_LINE()schema "dbms_output" does not existDBMS_UTILITY.FORMAT_ERROR_BACKTRACE()schema "dbms_utility" does not existPRAGMA AUTONOMOUS_TRANSACTIONtype "autonomous_transaction" does not existROWID Implementation Details
Both IvorySQL 5.0 and rophy/IvorySQL implement ROWID via PR #749, but it's opt-in per table:
Comparison with Oracle:
CREATE TABLE t (...)CREATE TABLE t (...) WITH (rowid=on)AAASwtAAAAAAclRAAA(Base64)(16385,1)(oid, seq)Implementation Priority Recommendations
#in identifiers (scanner modification) - #1002default_with_rowid)v$mystat/v$statnameviews - #1003Test Environment
ivorysql/ivorysql:5.0-bookwormrophy/ivorysql:20251204-ab4128a