Skip to Main Content
  • Questions
  • Cannot convert working PL/SQL function with INTERVAL parameters to equivalent SQL MACRO ( neither TABLE not SCALAR )

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, IUDITH.

Asked: February 08, 2025 - 11:09 pm UTC

Last updated: February 11, 2025 - 1:47 pm UTC

Version: 19c, 23ai

Viewed 100+ times

You Asked

Hello All,

I have a PL/SQL function that takes two INTERVAL DAY TO SECOND parameters and returns a value of the same data type.

It works correctly as a regular PL/SQL function.

I try to convert it to an equivalent SQL MACRO, both as a TABLE (in 19c and 23ai ) and as a SCALAR macro
(in 23ai ) and they compile without error, but when trying to use them from a SELECT statement they both fail.

I cannot perform tracing for trying to debug the problem.

Also, using DBMS_UTILITY.EXPAND_SQL_TEXT cannot be used in this case, because it works only for a TABLE SQL Macro
and only when the SQL runs successfully.

As an enhancement suggestion, it would be extremely useful to have the ability to see the transformed SQL query
( after the macro replacement ) in all cases, TABLE or SCALAR, successful or not, either by using
DBMS_UTILITY.EXPAND_SQL_TEXT or by any other method.


I created a script for the test case, under the link below:

https://livesql.oracle.com/ords/livesql/s/czlvwpdwtohm5u5l6njsmw4h9

and, although it appears as "Publicly shareable", the submission page DOES NOT allow me to enter it in the URL box !



Thanks a lot in advance for your help !
Iudith Mentzel
( 37 years of using Oracle, not just 35 as the dropbox on this submit page allows :) )



and Chris said...

Yep, there's a problem with passing interval values. I've raised this internally. You can pass interval values as bind variables, so use this as a workaround:

create or replace function f ( 
  period interval day to second 
) return clob sql_macro as
begin
  return ' select period ';
end;
/

declare 
  p interval day to second := interval '5' minute;
begin 
  for rws in (
    select * from f ( p )
  ) loop 
    dbms_output.put_line ( rws.period );
  end loop;
end;
/
+000000000 00:05:00.000000000


When it comes to DBMS_UTILITY.EXPAND_SQL_TEXT - you can't see the final SQL statement because there's a parse error. So there is no valid statement!

It's the same as passing any invalid SQL to this - you get an error, not a SQL statement:

declare
  l_clob clob;
begin
  dbms_utility.expand_sql_text (
    input_sql_text  => q'! select junk sql !',
    output_sql_text => l_clob  );
  dbms_output.put_line(l_clob);
end;
/
ORA-24256: EXPAND_SQL_TEXT failed with ORA-00904: "JUNK": invalid identifier

Rating

  (2 ratings)

Comments

Another work-around

Iudith Mentzel, February 10, 2025 - 8:29 pm UTC

Hi Chris,
Thanks a lot for your answer and for raising the issue internally.

I also found a little "exotic" workaround as follows:

WITH PARM (
V_INT,
V_UNIT
) AS (
SELECT
INTERVAL '10' MINUTE,
INTERVAL '5' MINUTE
FROM
DUAL
)
SELECT *
FROM
PARM P,
LATERAL(
SELECT * FROM ROUND_INTERVAL_MACRO (P.V_INT, P.V_UNIT)
)
/

V_INT V_UNIT RND
------- ------ -------
PT10M PT5M PT10M

It was a good exercise anyway :)

I think that we need in any case some way to see the "final" statement that is parsed, for both TABLE and SCALAR macros.

Thanks a lot & Best Regards,
Iudith

Yet another work-around ... and problem !

Iudith Mentzel, February 10, 2025 - 10:25 pm UTC

Hi Chris again:

Here is an even simpler work-around that works for the original TABLE macro:

select *
from round_interval_macro(
(select interval '10' minute from dual),
(select interval '5' minute from dual)
)
/

This one works even if I did not supply a column alias to the CASE expression inside the MACRO :)


For a simple SCALAR MACRO equivalent of your function, the same work-around still works:

create or replace function f_scalar (
period interval day to second
) return clob sql_macro (SCALAR) as
begin
return ' select period ';
end;
/

select f_scalar ( (SELECT interval '5' minute) )
from dual
/

F_SCALAR((SELECTINTERVAL'5'MINUTE))
------------------------------------
+00 00:05:00

But, for the original SCALAR macro

select round_interval_scalar (
(select interval '10' minute from dual),
(select interval '5' minute from dual) )
from dual
/

I still get either the same error ORA-62565 or
ORA-03113: end-of-file on communication channel

This depends on the database and on whether an alias is added or not to the CASE expression inside the MACRO.


Best Regards,
Iudith
Chris Saxon
February 11, 2025 - 1:47 pm UTC

OK, thanks for looking into this further; I'll inform the developers.

More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here