Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions contrib/ivorysql_ora/expected/ora_sysview.out
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,16 @@ END;
/
-- select ... from all_source
SELECT NAME, LINE, TEXT FROM ALL_SOURCE WHERE NAME = 'func_quotes_lower';
name | line | text
-------------------+------+-----------------------------------------------
func_quotes_lower | 1 | BEGIN
func_quotes_lower | 2 | RETURN 'func_quotes_lower'::VARCHAR2;
func_quotes_lower | 3 | END
(3 rows)
name | line | text
-------------------+------+---------------------------------------------------------
func_quotes_lower | 1 | FUNCTION public."FUNC_QUOTES_LOWER"(id pg_catalog.int4)
func_quotes_lower | 2 | RETURN varchar2
func_quotes_lower | 3 | AUTHID DEFINER
func_quotes_lower | | IS
func_quotes_lower | | BEGIN
func_quotes_lower | | RETURN 'func_quotes_lower'::VARCHAR2;
func_quotes_lower | | END;
(7 rows)

-- data_type and pls_type in all_arguments
CREATE OR REPLACE FUNCTION FUNC_22_ARG_TYPES
Expand Down
102 changes: 92 additions & 10 deletions contrib/ivorysql_ora/src/sysview/sysview--1.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ SELECT
ELSE 'PROCEDURE'
END::VARCHAR2(12) AS TYPE,
GENERATE_SERIES(1::INTEGER, SYS._ORA_SRC_COUNT(P.OID))::NUMBER AS LINE,
UNNEST(STRING_TO_ARRAY(P.PROSRC, CHR(10)))::VARCHAR2(4000) AS TEXT,
UNNEST(STRING_TO_ARRAY(substring(pg_get_functiondef(P.OID), length('CREATE OR REPLACE ') + 1), CHR(10)))::VARCHAR2(4000) AS TEXT,
0::VARCHAR2(256) AS ORIGIN_CON_ID
Comment on lines 365 to 367
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix LINE/TEXT mismatch in ALL_SOURCE (uses pg_get_functiondef for TEXT but PROSRC for LINE).

LINE is derived from SYS._ORA_SRC_COUNT(P.OID) which counts PROSRC lines, while TEXT now comes from pg_get_functiondef(...). This misaligns rows. Align both by switching DBA_SOURCE/ALL_SOURCE/USER_SOURCE to the same source and updating SYS._ORA_SRC_COUNT accordingly.

Apply these diffs:

  1. Use pg_get_functiondef in DBA_SOURCE TEXT and keep LINE in sync:
-   GENERATE_SERIES(1::INTEGER, SYS._ORA_SRC_COUNT(P.OID))::NUMBER AS LINE,
-   UNNEST(STRING_TO_ARRAY(P.PROSRC, CHR(10)))::VARCHAR2(4000) AS TEXT,
+   GENERATE_SERIES(1::INTEGER, SYS._ORA_SRC_COUNT(P.OID))::NUMBER AS LINE,
+   UNNEST(STRING_TO_ARRAY(substring(pg_get_functiondef(P.OID), length('CREATE OR REPLACE ') + 1), CHR(10)))::VARCHAR2(4000) AS TEXT,
  1. Count lines from the same definition text and mark the function STABLE (not IMMUTABLE):
 CREATE OR REPLACE FUNCTION SYS._ORA_SRC_COUNT(PROID OID)
 RETURNS INTEGER AS $$
@@
 BEGIN
-   SELECT
-       COUNT(1)
-   FROM
-   (
-       SELECT
-           UNNEST(STRING_TO_ARRAY(PROSRC, CHR(10)))
-       FROM
-           PG_PROC
-       WHERE
-           OID = $1
-   ) AS SQ
+   SELECT COUNT(*)
+   FROM (
+       SELECT UNNEST(
+         STRING_TO_ARRAY(
+           substring(pg_get_functiondef($1), length('CREATE OR REPLACE ') + 1),
+           CHR(10)
+         )
+       )
+   ) AS sq
    INTO RET;
    RETURN RET;
 END;
-$$ LANGUAGE PLPGSQL IMMUTABLE;
+$$ LANGUAGE PLPGSQL STABLE;

Also update USER_SOURCE to match (see comment below).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In contrib/ivorysql_ora/src/sysview/sysview--1.0.sql around lines 365 to 367,
the ALL_SOURCE row generation is mismatched: LINE is computed from
SYS._ORA_SRC_COUNT(P.OID) (which counts PROSRC lines) while TEXT comes from
pg_get_functiondef(P.OID). Fix by switching LINE generation to count lines from
the same pg_get_functiondef text (i.e., update SYS._ORA_SRC_COUNT to base its
count on pg_get_functiondef output), change any function declaration using
IMMUTABLE to STABLE for that helper so it can call pg_get_functiondef, and
ensure USER_SOURCE/DBA_SOURCE are updated identically to use pg_get_functiondef
for TEXT and the new line-counting function for LINE so both columns are derived
from the same source.

FROM
PG_PROC AS P
Expand Down Expand Up @@ -392,7 +392,7 @@ SELECT
ELSE 'PROCEDURE'
END::VARCHAR2(12) AS TYPE,
GENERATE_SERIES(1::INTEGER, SYS._ORA_SRC_COUNT(P.OID))::NUMBER AS LINE,
UNNEST(STRING_TO_ARRAY(P.PROSRC, CHR(10)))::VARCHAR2(4000) AS TEXT,
UNNEST(STRING_TO_ARRAY(substring(pg_get_functiondef(P.OID), length('CREATE OR REPLACE ') + 1), CHR(10)))::VARCHAR2(4000) AS TEXT,
0::VARCHAR2(256) AS ORIGIN_CON_ID
Comment on lines 394 to 396
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

USER_SOURCE has the same LINE/TEXT mismatch.

Mirror the fix used in ALL_SOURCE/DBA_SOURCE so LINE and TEXT derive from the same definition text.

-   GENERATE_SERIES(1::INTEGER, SYS._ORA_SRC_COUNT(P.OID))::NUMBER AS LINE,
-   UNNEST(STRING_TO_ARRAY(substring(pg_get_functiondef(P.OID), length('CREATE OR REPLACE ') + 1), CHR(10)))::VARCHAR2(4000) AS TEXT,
+   GENERATE_SERIES(1::INTEGER, SYS._ORA_SRC_COUNT(P.OID))::NUMBER AS LINE,
+   UNNEST(STRING_TO_ARRAY(substring(pg_get_functiondef(P.OID), length('CREATE OR REPLACE ') + 1), CHR(10)))::VARCHAR2(4000) AS TEXT,

(After applying the prior _ORA_SRC_COUNT change, this view will stay consistent.)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In contrib/ivorysql_ora/src/sysview/sysview--1.0.sql around lines 394 to 396,
the view uses SYS._ORA_SRC_COUNT(P.OID) for LINE but builds TEXT from
pg_get_functiondef(P.OID) separately, causing LINE/TEXT mismatch; refactor so
both LINE and TEXT come from the same computed definition text (e.g., compute
def := substring(pg_get_functiondef(P.OID), length('CREATE OR REPLACE ') + 1) or
equivalent in a subquery/CTE), use SYS._ORA_SRC_COUNT on that same def for
GENERATE_SERIES bounds and unnest STRING_TO_ARRAY(def, CHR(10)) for TEXT, and
keep ORIGIN_CON_ID as before.

FROM
PG_PROC AS P
Expand Down Expand Up @@ -461,6 +461,9 @@ SELECT
END::NUMBER AS SEQUENCE,
0::NUMBER AS DATA_LEVEL,
CASE
WHEN ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'table' OR ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'TABLE'
OR ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'view' OR ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'VIEW'
THEN 'PL/SQL RECORD'
WHEN T.TYPNAME = ANY(ARRAY['int2', 'int4', 'int8',
'numeric', 'number'])
THEN 'NUMBER'
Expand All @@ -487,6 +490,8 @@ SELECT
ELSE NULL
END::VARCHAR2(9) AS IN_OUT,
CASE
WHEN ARG.DATA_LENGTH IS NOT NULL
THEN ARG.DATA_LENGTH
WHEN T.TYPNAME = ANY(ARRAY['int2', 'int4', 'int8',
'float4', 'float8',
'numeric', 'number'])
Expand All @@ -496,6 +501,8 @@ SELECT
ELSE NULL
END::NUMBER AS DATA_LENGTH,
CASE
WHEN ARG.DATA_PRECISION IS NOT NULL
THEN ARG.DATA_PRECISION
WHEN T.TYPNAME = ANY(ARRAY['int2', 'int4', 'int8'])
THEN 38
WHEN T.TYPNAME = 'float4'
Expand All @@ -509,6 +516,8 @@ SELECT
ELSE NULL
END::NUMBER AS DATA_PRECISION,
CASE
WHEN ARG.DATA_SCALE IS NOT NULL
THEN ARG.DATA_SCALE
WHEN T.TYPNAME = ANY(ARRAY['float4', 'float8'])
THEN -127
ELSE NULL
Expand All @@ -531,12 +540,29 @@ SELECT
THEN 'NCHAR_CS'
END::VARCHAR2(44) AS CHARACTER_SET_NAME,
NULL::VARCHAR2(128) AS TYPE_OWNER,
NULL::VARCHAR2(128) AS TYPE_NAME,
NULL::VARCHAR2(128) AS TYPE_SUBNAME,
CASE
WHEN ARG.TYPE_NAME != '_NULL_'
THEN SYS.ORA_CASE_TRANS(ARG.TYPE_NAME::VARCHAR2)::VARCHAR2(128)
ELSE
NULL
END::VARCHAR2(128) AS TYPE_NAME,
CASE
WHEN ARG.TYPE_SUBNAME != '_NULL_'
THEN SYS.ORA_CASE_TRANS(ARG.TYPE_SUBNAME::VARCHAR2)::VARCHAR2(128)
ELSE
NULL
END::VARCHAR2(128) AS TYPE_SUBNAME,
NULL::VARCHAR2(128) AS TYPE_LINK,
NULL::VARCHAR2(128) AS TYPE_OBJECT_TYPE,
CASE
WHEN T.TYPTYPE = 'b'
WHEN ARG.TYPE_OBJECT_TYPE != '_NULL_'
THEN SYS.ORA_CASE_TRANS(ARG.TYPE_OBJECT_TYPE::VARCHAR2)::VARCHAR2(128)
ELSE
NULL
END::VARCHAR2(128) AS TYPE_OBJECT_TYPE,
Comment on lines +543 to +561
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid sentinel string 'NULL' in TYPE_ columns; use NULLIF for cleaner SQL.*

Sentinel comparison with "!= 'NULL'" is brittle and NULL-unsafe. Prefer NULLIF and a single expression.

-   CASE
-      WHEN ARG.TYPE_NAME != '_NULL_'
-           THEN SYS.ORA_CASE_TRANS(ARG.TYPE_NAME::VARCHAR2)::VARCHAR2(128)
-      ELSE
-           NULL
-   END::VARCHAR2(128) AS TYPE_NAME,
+   SYS.ORA_CASE_TRANS(NULLIF(ARG.TYPE_NAME, '_NULL_')::VARCHAR2)::VARCHAR2(128) AS TYPE_NAME,

-   CASE
-      WHEN ARG.TYPE_SUBNAME != '_NULL_'
-           THEN SYS.ORA_CASE_TRANS(ARG.TYPE_SUBNAME::VARCHAR2)::VARCHAR2(128)
-      ELSE
-           NULL
-   END::VARCHAR2(128) AS TYPE_SUBNAME,
+   SYS.ORA_CASE_TRANS(NULLIF(ARG.TYPE_SUBNAME, '_NULL_')::VARCHAR2)::VARCHAR2(128) AS TYPE_SUBNAME,

-   CASE
-      WHEN ARG.TYPE_OBJECT_TYPE != '_NULL_'
-           THEN SYS.ORA_CASE_TRANS(ARG.TYPE_OBJECT_TYPE::VARCHAR2)::VARCHAR2(128)
-      ELSE
-           NULL
-   END::VARCHAR2(128) AS TYPE_OBJECT_TYPE,
+   SYS.ORA_CASE_TRANS(NULLIF(ARG.TYPE_OBJECT_TYPE, '_NULL_')::VARCHAR2)::VARCHAR2(128) AS TYPE_OBJECT_TYPE,

If possible, also switch the SRF to emit NULL instead of 'NULL'.

Also applies to: 557-561, 563-565

CASE
WHEN (T.TYPTYPE = 'b' OR T.TYPTYPE = 'c') AND ARG.PLS_TYPE IS NOT NULL
THEN SYS.ORA_CASE_TRANS(ARG.PLS_TYPE)
WHEN T.TYPTYPE = 'b' AND ARG.PLS_TYPE IS NULL
THEN SYS.ORA_CASE_TRANS(T.OID::REGTYPE::VARCHAR2)
WHEN T.TYPTYPE = 'd' AND T.TYPNAME = 'raw'
THEN 'RAW'
Expand Down Expand Up @@ -597,6 +623,21 @@ FROM
PG_PROC
) AS SQ
ON P.OID = SQ.OID
LEFT JOIN
(
SELECT
OID,
POSITION,
TYPE_NAME,
TYPE_SUBNAME,
TYPE_OBJECT_TYPE,
DATA_LENGTH,
DATA_PRECISION,
DATA_SCALE,
PLS_TYPE
FROM
pg_get_function_arg_reference_typerowtype()
) AS ARG ON ARG.OID = SQ.OID AND ARG.POSITION = SQ.POSITION
LEFT JOIN PG_TYPE AS T
ON SQ.DATA_TYPE = T.OID
LEFT JOIN PG_TRIGGER AS TR
Expand Down Expand Up @@ -635,6 +676,9 @@ SELECT
END::NUMBER AS SEQUENCE,
0::NUMBER AS DATA_LEVEL,
CASE
WHEN ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'table' OR ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'TABLE'
OR ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'view' OR ARG.TYPE_OBJECT_TYPE::VARCHAR2 = 'VIEW'
THEN 'PL/SQL RECORD'
WHEN T.TYPNAME = ANY(ARRAY['int2', 'int4', 'int8',
'numeric', 'number'])
THEN 'NUMBER'
Expand All @@ -661,6 +705,8 @@ SELECT
ELSE NULL
END::VARCHAR2(9) AS IN_OUT,
CASE
WHEN ARG.DATA_LENGTH IS NOT NULL
THEN ARG.DATA_LENGTH
WHEN T.TYPNAME = ANY(ARRAY['int2', 'int4', 'int8',
'float4', 'float8',
'numeric', 'number'])
Expand All @@ -670,6 +716,8 @@ SELECT
ELSE NULL
END::NUMBER AS DATA_LENGTH,
CASE
WHEN ARG.DATA_PRECISION IS NOT NULL
THEN ARG.DATA_PRECISION
WHEN T.TYPNAME = ANY(ARRAY['int2', 'int4', 'int8'])
THEN 38
WHEN T.TYPNAME = 'float4'
Expand All @@ -683,6 +731,8 @@ SELECT
ELSE NULL
END::NUMBER AS DATA_PRECISION,
CASE
WHEN ARG.DATA_SCALE IS NOT NULL
THEN ARG.DATA_SCALE
WHEN T.TYPNAME = ANY(ARRAY['float4', 'float8'])
THEN -127
ELSE NULL
Expand All @@ -705,12 +755,29 @@ SELECT
THEN 'NCHAR_CS'
END::VARCHAR2(44) AS CHARACTER_SET_NAME,
NULL::VARCHAR2(128) AS TYPE_OWNER,
NULL::VARCHAR2(128) AS TYPE_NAME,
NULL::VARCHAR2(128) AS TYPE_SUBNAME,
CASE
WHEN ARG.TYPE_NAME != '_NULL_'
THEN SYS.ORA_CASE_TRANS(ARG.TYPE_NAME::VARCHAR2)::VARCHAR2(128)
ELSE
NULL
END::VARCHAR2(128) AS TYPE_NAME,
CASE
WHEN ARG.TYPE_SUBNAME != '_NULL_'
THEN SYS.ORA_CASE_TRANS(ARG.TYPE_SUBNAME::VARCHAR2)::VARCHAR2(128)
ELSE
NULL
END::VARCHAR2(128) AS TYPE_SUBNAME,
NULL::VARCHAR2(128) AS TYPE_LINK,
NULL::VARCHAR2(128) AS TYPE_OBJECT_TYPE,
CASE
WHEN T.TYPTYPE = 'b'
WHEN ARG.TYPE_OBJECT_TYPE != '_NULL_'
THEN SYS.ORA_CASE_TRANS(ARG.TYPE_OBJECT_TYPE::VARCHAR2)::VARCHAR2(128)
ELSE
NULL
END::VARCHAR2(128) AS TYPE_OBJECT_TYPE,
CASE
WHEN (T.TYPTYPE = 'b' OR T.TYPTYPE = 'c') AND ARG.PLS_TYPE IS NOT NULL
THEN SYS.ORA_CASE_TRANS(ARG.PLS_TYPE)
WHEN T.TYPTYPE = 'b' AND ARG.PLS_TYPE IS NULL
THEN SYS.ORA_CASE_TRANS(T.OID::REGTYPE::VARCHAR2)
WHEN T.TYPTYPE = 'd' AND T.TYPNAME = 'raw'
THEN 'RAW'
Expand Down Expand Up @@ -771,6 +838,21 @@ FROM
PG_PROC
) AS SQ
ON P.OID = SQ.OID
LEFT JOIN
(
SELECT
OID,
POSITION,
TYPE_NAME,
TYPE_SUBNAME,
TYPE_OBJECT_TYPE,
DATA_LENGTH,
DATA_PRECISION,
DATA_SCALE,
PLS_TYPE
FROM
pg_get_function_arg_reference_typerowtype()
) AS ARG ON ARG.OID = SQ.OID AND ARG.POSITION = SQ.POSITION
LEFT JOIN PG_TYPE AS T
ON SQ.DATA_TYPE = T.OID
LEFT JOIN PG_TRIGGER AS TR
Expand Down
Loading
Loading