FOR var IN (SELECT ...) |
Implicit RECORD declaration for FOR loop cursor variables |
❌ |
❌ |
✅ |
#983 Open |
EXCEPTION type |
User-defined exception types with RAISE/WHEN support |
❌ |
❌ |
✅ |
#972 Merged |
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