Skip to content

Compatibility: Included Packages

The 10 packages below are fully included in orafce_no_c. See How to Read These Tables for what the columns mean — in particular, N/A rows are included too: if real orafce's own version of a function was already pure SQL/PL/pgSQL, orafce_no_c copies it over verbatim and installs it automatically along with everything else. You never need to manually pull an N/A function out of real orafce yourself.

dbms_assert

Function Includes C Is Converted
dbms_assert.enquote_literal Y Y
dbms_assert.enquote_name Y Y
dbms_assert.noop Y Y
dbms_assert.object_name Y Y
dbms_assert.qualified_sql_name Y Y
dbms_assert.schema_name Y Y
dbms_assert.simple_sql_name Y Y

dbms_output

Function Includes C Is Converted
dbms_output.disable Y Y
dbms_output.enable Y Y
dbms_output.get_line Y Y
dbms_output.get_lines Y Y
dbms_output.new_line Y Y
dbms_output.put Y Y
dbms_output.put_line Y Y
dbms_output.serveroutput Y Y

dbms_random

Function Includes C Is Converted
dbms_random.initialize Y Y
dbms_random.normal Y Y
dbms_random.random Y Y
dbms_random.seed Y Y
dbms_random.string Y Y
dbms_random.terminate Y Y
dbms_random.value Y Y

Every function here is converted, but not every value produced is byte-for-byte reproducible against real orafce — see Behavioral Differences from Real orafce for what that means in practice and why it's still a safe, correct conversion.

dbms_utility

Function Includes C Is Converted
dbms_utility.format_call_stack Y N
dbms_utility.get_time Y Y

oracle

By far the largest package — 105 objects, more than the other 14 packages combined.

Function Includes C Is Converted
oracle.add_days_to_timestamp N N/A
oracle.add_months Y Y
oracle.bitand N N/A
oracle.btrim Y Y
oracle.cosh N N/A
oracle.date [DOMAIN] N N/A
oracle.dba_segments [VIEW] N N/A
oracle.dbtimezone Y Y
oracle.decode Y Y
oracle.dual [VIEW] N N/A
oracle.dump Y N
oracle.get_full_version_num Y Y
oracle.get_major_version Y Y
oracle.get_major_version_num Y Y
oracle.get_platform Y N
oracle.get_status Y Y
oracle.greatest Y Y
oracle.instr Y Y
oracle.last_day Y Y
oracle.least Y Y
oracle.length Y Y
oracle.lengthb Y Y
oracle.listagg [AGGREGATE] Y Y
oracle.listagg1_transfn Y Y
oracle.listagg2_transfn Y N
oracle.listagg_finalfn Y Y
oracle.lnnvl Y Y
oracle.lpad Y Y
oracle.ltrim Y Y
oracle.median [AGGREGATE] Y Y
oracle.median4_finalfn Y Y
oracle.median4_transfn Y Y
oracle.median8_finalfn Y Y
oracle.median8_transfn Y Y
oracle.mod N N/A
oracle.months_between Y Y
oracle.nanvl N N/A
oracle.next_day Y Y
oracle.nlssort Y N
oracle.numtodsinterval N N/A
oracle.nvarchar2 Y Y*
oracle.nvarchar2 [TYPE] Y N
oracle.nvarchar2_transform Y N
oracle.nvarchar2in Y N
oracle.nvarchar2out Y N
oracle.nvarchar2recv Y N
oracle.nvarchar2send Y N
oracle.nvarchar2typmodin Y N
oracle.nvarchar2typmodout Y N
oracle.nvl Y Y
oracle.nvl2 Y Y
oracle.orafce__obsolete_to_date Y Y
oracle.orafce_concat2 Y N*
oracle.product_component_version [VIEW] Y N*
oracle.regexp_count N N/A
oracle.regexp_count_pattern_fix N N/A
oracle.regexp_instr Y Y
oracle.regexp_like N N/A
oracle.regexp_replace Y Y
oracle.regexp_substr N N/A
oracle.remainder Y Y
oracle.replace_empty_strings Y Y
oracle.replace_null_strings Y Y
oracle.round Y Y
oracle.rpad Y Y
oracle.rtrim Y Y
oracle.sessiontimezone Y Y
oracle.set_nls_sort Y N*
oracle.sinh N N/A
oracle.strposb Y Y
oracle.substr Y Y
oracle.substrb Y Y
oracle.subtract N N/A
oracle.sys_extract_utc Y Y
oracle.sys_guid Y Y
oracle.sysdate Y Y
oracle.tanh N N/A
oracle.to_char Y Y
oracle.to_date N N/A
oracle.to_multi_byte Y Y
oracle.to_number Y Y
oracle.to_single_byte Y Y
oracle.translate_oracle_modifiers N N/A
oracle.trunc Y Y
oracle.unistr Y Y
oracle.user_cons_columns [VIEW] N N/A
oracle.user_constraints [VIEW] N N/A
oracle.user_ind_columns [VIEW] N N/A
oracle.user_objects [VIEW] N N/A
oracle.user_procedures [VIEW] N N/A
oracle.user_source [VIEW] N N/A
oracle.user_tab_columns [VIEW] N N/A
oracle.user_tables [VIEW] N N/A
oracle.user_views [VIEW] N N/A
oracle.varchar2 Y Y*
oracle.varchar2 [TYPE] Y N
oracle.varchar2_transform Y N
oracle.varchar2in Y N
oracle.varchar2out Y N
oracle.varchar2recv Y N
oracle.varchar2send Y N
oracle.varchar2typmodin Y N
oracle.varchar2typmodout Y N
oracle.wm_concat [AGGREGATE] Y Y
oracle.wm_concat_transfn Y Y

A few rows above need more explanation than the table can give:

varchar2/nvarchar2 and their 14 supporting [TYPE]/_transform/I-O/typmod functions remain genuinely unconvertible — no PL/pgSQL or SQL-language function can declare the cstring parameter a custom base type's I/O functions require. The two top-level rows are marked Y* rather than plain N because an optional, separately-installed family of differently-named domains is available as a workaround for actually using the type in migrated code — see Working with Types onward. It's a genuinely weaker claim than Y: a different object, not a true type conversion (see Why These Types Error Instead of Truncating), and not part of the core install.

lengthb/strposb/substrb were originally excluded as "convertible in isolation, but pointless without a byte-oriented type to pair with" — the same reasoning used for nlssort/set_nls_sort below. That objection is resolved by the VARCHAR2/NVARCHAR2 domain family, so all three are now included unconditionally — they ship in the core install regardless of whether you also install the optional type add-on.

listagg2_transfn is marked N, not Y — nothing by that name exists in orafce_no_c. Real orafce's 2-argument oracle.listagg(text, text) aggregate (with an explicit delimiter) is backed by this C function; this port's equivalent aggregate instead reuses PostgreSQL core's own string_agg_transfn/string_agg_finalfn directly. The aggregate's outward behavior is fully available either way — this is a bypass of the specific support function, not a gap in what you can actually do.

The 12 [VIEW]-tagged rows are Oracle data-dictionary emulation views (dual, the various user_* catalog views, dba_segments, product_component_version). 11 of them are plain CREATE VIEW statements over information_schema/pg_catalog in real orafce too — no C anywhere — and are copied verbatim. product_component_version is the one exception (N*): one of its 3 output columns calls oracle.get_platform(), which is itself excluded (see below), so it's deferred rather than shipped with a fudged column.

dump and get_platform are excluded outright: dump() does a raw memory dump of an arbitrary value, and get_platform() returns a hardcoded '64bit'/'32bit' string baked in at compile time — neither has any SQL-level equivalent.

nlssort/set_nls_sort are excluded together: nlssort() calls the C library's strxfrm() against a caller-supplied, arbitrary named locale, and PostgreSQL's own collation/sort behavior is fixed at column/expression definition time, not late-bound per call — there's no way to run strxfrm() against an arbitrary locale from SQL. Excluding one without the other would leave neither useful.

orafce_concat2 is excluded: it's the internal helper backing the || operator for varchar2/nvarchar2 values, and has no purpose once those types themselves are excluded. Note it isn't just "pointless" in the abstract — it doesn't even need reviving for the optional domain add-on, since domains inherit || from their underlying text type for free. For example:

SELECT 'hello'::oracle.varchar_100c || 'world'::oracle.varchar_50c;
--> 'helloworld'   (plain text, NOT oracle.varchar_100c or oracle.varchar_50c)

SELECT pg_typeof('hello'::oracle.varchar_100c || 'world'::oracle.varchar_50c);
--> text

|| between two domain-typed values resolves through ordinary domain-to-base-type coercion straight to core text || text — no custom operator needed, and no length check happens at concatenation time either, since it's just plain text at that point. The check only reappears if the result is cast or assigned back into a domain:

SELECT (repeat('a', 60)::oracle.varchar_50c || repeat('b', 60)::oracle.varchar_100c)
         ::oracle.varchar_50c;
--> ERROR: value for domain oracle.varchar_50c violates check constraint "varchar_50c_check"

That's the same outcome real orafce's orafce_concat2 exists to guarantee for varchar2/nvarchar2 — a too-long result gets caught the moment it's forced back into a length-constrained type — achieved here for free by ordinary domain behavior, with nothing extra to port.

The reverse order — concatenating first, casting the whole thing to a domain afterward — behaves differently, and it's worth seeing why:

SELECT ('hello' || 'world')::oracle.varchar_100c;
--> 'helloworld'   (this time the result type IS oracle.varchar_100c)

SELECT pg_typeof(('hello' || 'world')::oracle.varchar_100c);
--> oracle.varchar_100c

Here 'hello' || 'world' runs first as ordinary text || text (neither side is domain-typed yet), producing a plain text value — and only then does the ::oracle.varchar_100c cast wrap that already-finished value, running the CHECK once and handing back the domain type on success. That's different from the earlier example above, where the || operator itself was resolving between two already domain-typed operands and decayed to text as a side effect of that resolution — no cast was involved there at all. Either way, an oversized result still errors the same way, since nothing here ever truncates:

SELECT (repeat('a', 60) || repeat('b', 60))::oracle.varchar_100c;
--> ERROR: value for domain oracle.varchar_100c violates check constraint "varchar_100c_check"

plunit

Function Includes C Is Converted
plunit.assert_equals Y Y
plunit.assert_false Y Y
plunit.assert_not_equals Y Y
plunit.assert_not_null Y Y
plunit.assert_null Y Y
plunit.assert_true Y Y
plunit.fail Y Y

plvchr

Function Includes C Is Converted
plvchr._is_kind Y Y
plvchr.char_name Y Y
plvchr.first Y Y
plvchr.is_blank N N/A
plvchr.is_digit N N/A
plvchr.is_letter N N/A
plvchr.is_other N N/A
plvchr.is_quote N N/A
plvchr.last Y Y
plvchr.nth Y Y
plvchr.quoted1 N N/A
plvchr.quoted2 N N/A
plvchr.stripped N N/A

plvdate

Function Includes C Is Converted
plvdate.add_bizdays Y Y
plvdate.bizdays_between Y Y
plvdate.days_inmonth Y Y
plvdate.default_holidays Y Y
plvdate.include_start Y Y
plvdate.including_start Y Y
plvdate.isbizday Y Y
plvdate.isleapyear Y Y
plvdate.nearest_bizday Y Y
plvdate.next_bizday Y Y
plvdate.noinclude_start N N/A
plvdate.prev_bizday Y Y
plvdate.set_nonbizday Y Y
plvdate.unset_nonbizday Y Y
plvdate.unuse_easter N N/A
plvdate.unuse_great_friday N N/A
plvdate.use_easter Y Y
plvdate.use_great_friday Y Y
plvdate.using_easter Y Y
plvdate.using_great_friday Y Y
plvdate.version Y Y

plvstr

Function Includes C Is Converted
plvstr.betwn Y Y
plvstr.instr Y Y
plvstr.is_prefix Y Y
plvstr.left Y Y
plvstr.lpart Y Y
plvstr.lstrip Y Y
plvstr.normalize Y Y
plvstr.right Y Y
plvstr.rpart Y Y
plvstr.rstrip Y Y
plvstr.rvrs Y Y
plvstr.substr Y Y
plvstr.swap Y Y

Three functions in this package (betwn, is_prefix, normalize) have confirmed bugs in real orafce itself — some deliberately preserved bug-for-bug, one deliberately fixed. See Confirmed Bugs Found in Real orafce before relying on exact behavioral parity for these three.

plvsubst

Function Includes C Is Converted
plvsubst.setsubst Y Y
plvsubst.string Y Y
plvsubst.subst Y Y

Continue to Compatibility: Excluded Packages.