Nested PIPELINED function is skipped by Oracle - oracle

I'll post a trivial example, which actually works, just to get an approximate picture of what I'm trying to achieve:
Here is the 'inner' function which takes the data from some table, called test_tab:
create or replace function test_inner RETURN num_typ PIPELINED
IS
BEGIN
FOR cur in (
SELECT x FROM test_tab
)
LOOP
PIPE ROW(cur.x);
END LOOP;
END;
/
Here is the 'outer' function which uses the result of inner function and transforms them appropriately:
create or replace function test_outer RETURN num_typ PIPELINED
IS
BEGIN
FOR x IN (
SELECT * FROM table(test_inner())
)
LOOP
PIPE ROW(x.column_value * 2);
END LOOP;
END;
/
And here is how I use it:
begin
execute immediate 'insert into test_tab(x) values(1)';
execute immediate 'insert into test_tab(x) values(2)';
execute immediate 'insert into test_tab(x) values(3)';
FOR x IN (
select * from table(test_outer())
) LOOP
DBMS_OUTPUT.put_line(x.column_value);
END LOOP;
end;
/
The problem is that test_inner function seems to be ignored by Oracle. When it is called separately, it 'sees' the data inserted prior to its execution. But when it's called as a part of test_outer it doesn't return any data, or maybe doesn't get called at all.
Like I said, the above example will work. But my case is a little bit more complex, so I can't post it entirely.

The test case you have posted does not reproduce the problem you claim to be seeing. So it is not a test case.
#AlexPoole has provided you with some other ideas. Basically there is nothing further we can do unless you can post a better test case, given that you cannot post the entire things (and we don't want to go through hundreds of lines of somebody else's shonky code - I for one get enough of that debugging my own stuff).
Producing a poor test case has not been a waste of time. At least you can rule out certain things: it's nothing to do with one pipelined function calling another. So it's clearly something in your specific implementation. Perhaps not in the internal function logic, but how they are called, the data they work with or some other part of the infrastructure.
All you can do is analyse the individual parts. Start with the core component, and build out, adding other components until you find the bit which breaks. Yes this is a tedious chore. But from your comments it sounds like you're quite a way through this process already.
I'm marking this CW as it isn't an answer to the question, just an extended comment.

Your both pipelined functions in fact are syntactic wrong: you are missing RETURN
See docs

Related

Can we declare and use a cursor in a package specification without a body?

It's said in database PL/SQL language reference in topic 10.1 What is a package? that:
If the public items include cursors or subprograms, then the package must also have a body. The body must define queries for public cursors and code for public subprograms.
I've tested cursor package spec without body and it worked fine (in DB version 19c):
create or replace package some_pak is
cursor c is select * from employees where employee_id <102;
end;
begin
for i in some_pak.c
loop
dbms_output.put_line(i.employee_id|| ' '||i.first_name||' '|| i.salary);
end loop;
end;
Result:
100 Steven 24000
101 Neena 17000
What am I doing or understanding wrong?
I am preparing for 1z0-149 exam and want to know accurate information.
It is a bit misleading, but if you take the previous paragraph from the documentation into account:
A package always has a specification, which declares the public items that can be referenced from outside the package.
... and stress the declares in that, then it sort of makes sense; if you only declare a cursor, rather than declaring and defining as your example does, then you do need a body too. For example, your specification could do:
create or replace package some_pak is
cursor c return dual%rowtype;
end;
/
But if you tried to reference that cursor you'd get "ORA-04067: not executed, package body ... does not exist".
You would then need to define the cursor in the package body, e.g.:
create or replace package body some_pak is
cursor c return dual%rowtype is
select * from dual;
end;
/
Notice that you need to declare the return type, in both the specification and body. In your original version that isn't necessary, but here the declaration still has to tell callers the structure of the data the cursor will return. That is the API contract, if you like.
Declaring and defining the cursor separately means you can redefine the cursor by recompiling just the package body (as long as the projection remains the same, of course), avoiding invalidating anything that refers to it - as would happen if you recompiled the specification.
db<>fiddle
Splitting the declaration and definition would also allow you to hide (albeit not very securely) the actual cursor query by wrapping the package body, without wrapping the specification. Whether that would ever be useful is another matter, but thought it might be worth mentioning anyway.

Inline VS Linear String processing performance in Object Oriented Pascal - Delphi

Because of the close ending of one of my projects I wanned set up some discussion ( in case Rob does not provide very detailed answer :D ), I am more focusing of some memory and cycle optimizations in some hungry string processing areas. In my case I am interested in some performace tests, if anyone has made something like that, for particularry performance diff for two cases:
Case 1: I use string processing in in-line way so I have one extra lengthy line, for example,
RichEdit1.SelText := stringfunction1(stringfunction2(stringfunction3(stringfunction4, stringfunction5), stringfunction6, stringfunction7(stringfunction8))))
or
Case 2:
I just split all those functions so each has executed in seperate line and therefore I have to declare the variable that would buffer the return of each function.
P.S. I hope I have not mistaken with the brackets in Case 1.
So, what is your findings / opinion / critics about this question?
Maybe it is not simply worth time to gain some extra nanosecond?
Declaring variables wouldn't make any difference I believe.
When you call functions like this, the compiler needs to generate implicit string variables to keep the result of your functions. The way you are doing it, the main advantage would be that the compiler can decide to reuse a temp variable once it's done using it, but nothing prevent the compiler to do the same with explicit variables.
Actually, every time you call a function with a string result, the compiler need to create a temp variables, because function returning a string are actually implemented as a procedure with an additional var parameter.
For exemple:
function GetTempPath : string;
is really implemented this way
procedure GetTempPath(var S : string);
so, given following procedure:
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Text := GetTempPath;
end;
The compiler first allocate a temporary string variable. Calls GetTempPath with said temp variable in parameter. Once it returns, it takes this variable and set it to Memo1.Lines.Text. Essentially, what it really does is this:
procedure TForm1.Button1Click(Sender: TObject);
var S : string;
begin
GetTempPath(S);
Memo1.Lines.Text := S;
end;
and if you actually declare the function like the following, the compiler is smart enough to not create an additionnal variable.
procedure TForm1.Button1Click(Sender: TObject);
var S : string;
begin
S := GetTempPath;
Memo1.Lines.Text := S;
end;
The code
var
s1, s2: string;
begin
s1 := 'This is a very long string...';
s2 := s1;
end;
does not copy the string s1 into s2 (which could be a performance issue in a tight loop), but it simply instructs s2 to point to the same location in memory as s1. That is, in general, assigning strings to variables isn't a very bad thing.
In fact, I am not sure what method would produce the most efficient assembly code (if they are not identical!). Even in the in-lined case, the intermediate results have to be stored somewhere...
All-in-all, I definitely think you should go for the approach that is the most readble one (to a human programmer). The difference in performance should not even be detectable.
Okay.
I will try to put things together within two sentences. :)
String optimization
basically is premature optimmization
because of fact that it is bottleneck
of performance in VERY VERY VERY rear
situations or usecases.
Inline string usages main advantage is to use compilers features that allow to reuse previous return ( temp ) variables in further paramteric function calls. Still - if we intend to use linear operation(s), we should add GetTempPath() procedure before main string equalization code to make sure we use old temp variables still accessible in memory.

Can I set a state within a function?

I have this code:
procedure EstablishCommunication;
var
State : TStates;
Attempts : Byte;
procedure IncAttempts;
begin
Inc(Attempts);
end;
begin
State := stReadDeviceID;
Attempts := 0;
while True do
begin
if Attempts >= MAX_ATTEMPTS then
begin
State := stError;
end;
case State of
stReadDeviceID:
begin
// some code
IncAttempts;
end;
stError:
begin
// Error code
end;
...
...
...
I'd like to put the code that set state to stError within of the procedure IncAttempts, resulting:
procedure EstablishCommunication;
var
State : TStates;
Attempts : Byte;
procedure IncAttempts;
begin
Inc(Attempts);
if Attempts >= MAX_ATTEMPTS then
begin
State := stError;
end;
end;
begin
State := stReadDeviceID;
Attempts := 0;
while True do
begin
case State of
stReadDeviceID:
begin
// some code
IncAttempts;
end;
stError:
begin
// Error code
end;
...
...
...
So, can I move the code to IncAttempts?
Is this a code smell?
If yes, Can you advice me a better way?
I would see this as perfect valid code. I ask myself the following questions when declaring a method inside another. Most of the time I don't do it, but sometimes it's results in better code.
Will the internal function ever need to change as in a descendant class?
Can I override External method without calling the internal method and be OK?
Does the internal function have practical application outside of external method?
Is the internal function complex enough that it should be unit tested outside the scope of there external method?
If any of the above apply don't use an Internal Method.
However if if you don't have any of the above, and it can remove repeated code and/or simplify the design then you can consider using a internal function.
No real problem with that, should work just fine. You are already modifying another local variable Attempts so there is no reason why modifying State should smell more.
I do think you should be careful of using inline functions to much. The code often ends up hard to read/understand.
I would say that the new code have some whiff...
It all depends on how many states you manage in current code, and if the number of states could change in the future. Beware of how and when you set the state, and beware of how and when you check the state.
In the two code snippets you show, there is a minor difference:
In the first, original code, the current state is preserved through the iteration, and the new error-state is set in the beginning of the iteration, and it is always checked.
In the second, refactored code, the state is changed in the middle of the iteration, and it is only altered if the state is stReadDeviceID.
Now, if the last line in this while True do-iteration is if State = stError then Break;, then your first code will run the iteration one more time, changing the state to stError in the beginning if the iteration. Your second code will exit at the end of the current iteration, and the code in the stError-section of the case-statement will never be executed...
If you want to go all the way, and study the GoF's State Design Pattern, then take a look at these pages:
http://en.wikipedia.org/wiki/State_pattern (no Delphi code...)
http://sourcemaking.com/design_patterns/state (with Delphi code!)
http://www.dofactory.com/Patterns/PatternState.aspx (no Delphi code...)
http://conferences.embarcadero.com/article/32129#_Toc12157322 (with Delphi code!)

Does a begin-end block affect the performance of a conditional statement?

I am working with Delphi. Does it make any difference in performance if we write if condition in different ways? For example:
if (condition) then
someVar := someVal
else
someVar := someOtherVal;
Or we can write:
if (condition) then begin
someVar := someVal;
end else begin
someVar := someOtherVal;
end;
I prefer the second option just because it looks better than the first one.
No, there is no difference in performance, the code created will be identical.
An aspect that might be more important than that the second option looks nicer, is that it is better for maintainence. If you need to add another statement in the else block, you will not accidentally forget to add the begin and end, which would put the statement outside the if and always be executed.
This will not make a difference in performance.
begin and end tell the compiler where a block of code starts and finishes, but no computation needs to be done there.
Begin and End do not slow down your code, as others have already said. I am writing another answer to encourage you even more explicitly to ALWAYS use begin and end whenever you could use them.
It is good to be liberal with using Begin and End, and not worry about them slowing you down (because they don't).
If you go the other way, and leave out begin and end wherever you can, you get into a different type of trouble.
This has happened to me lots. You can get in trouble when you insert a line into a place where no begin and end statement exist. You then end up scratching your head wondering what you did that broke your code. Begin-end-everywhere, even where not needed, is standard operating procedure for a lot of Delphi coders.
The only thing you should keep in mind about if-elseif-else is to keep the common cases up in your code before edge cases, so that the least possible conditions are evaluated.

Oracle Default Values

I've got a quick question about default values in PL/SQL functions in Oracle. Take this program as an example;
create or replace
FUNCTION testFunction
(
varNumber IN NUMBER DEFAULT 0
)
RETURN NUMBER
AS
BEGIN
dbms_output.put_line(varNumber);
RETURN varNumber;
END;
The idea here being that if no value is specified for varNumber when this function is called, then it will take the value of 0.
Now, my problem is that my functions are getting called from a web services layer that will always pass in NULL as the value for parameters which it doesn't have a value for. Oracle interprets NULL as a value, and so does not initialise varNumber to its default of 0.
I can see why this approach makes sense, but I was wondering if there was a way to override this behaviour, and make it so that if a NULL value is passed, that it causes Oracle to assign the explicit DEFAULT value that is specified in the function header?
I have considered the option of doing a manual check...
IF(varNumber IS NULL) THEN
varNumber := 0;
END IF;
However, there are hundreds of functions where this may be an issue, never mind the large number of parameters per function, and so I'd prefer it if I could find a more general solution to the problem.
Cheers for any insight you can give.
Use NVL to define the value.
NVL( value_in, replace_with )
You can't assign values to an IN parameter, but you could make them IN/OUT and then set them. That raises a big potential for misuse and confusion, though.
So I think you'd do better with a local variable. But you can do it in the declaration. That is,
create or replace
FUNCTION testFunction
(
varNumber IN NUMBER DEFAULT 0
)
RETURN NUMBER
AS
vFix number := nvl(varNumber,0);
BEGIN
dbms_output.put_line(vFix);
RETURN vFix;
END;
Your manual check is the only way to safely do what you want.
You can write that in one line like this though:
varNumber = NVL(varNumber,0);
Good luck!

Resources