Inside Oracle APEX by Patrick Wolf

Caution: Apex_Item.Date_Popup and Oracle APEX 3.1

Just to let you know in case you are hitting the following problem or plan to upgrade to 3.1. The version of Apex_Item.Date_Popup which comes with Oracle APEX 3.1.0.00.32 has a "small" bug. The Date Picker will always write the return value into the first row, independent for which row you have opened the Date Picker.

Carl has already provided a workaround for the bug and I'm pretty sure it will be fixed in the first patchset of Oracle APEX 3.1.

Labels: ,


« ... Read full posting ... »

SQL embedded into PL/SQL

A few days ago I spoke with another developer about SQL embedded into PL/SQL code and how function calls are handled in the WHERE clause of SQL statements. There is sometimes confusion who (PL/SQL engine or SQL engine) is executing it, I thought it's a good idea to write a posting about it.

Last year I have already blogged about it in Caution when using PL/SQL functions in a SQL statement, but that was in the context of writing a stand alone SQL statement for a report, ... but what actually happens if you have a SQL embedded into PL/SQL like the following example procedure code in a package
PROCEDURE processEmps
( pDepartmentId IN NUMBER
)
IS
BEGIN
FOR rEMP IN
( SELECT EMPLOYEE_ID
FROM EMPLOYEES
WHERE SALARY > getAvgDeptSalary(pDepartmentId)
)
LOOP
NULL;
END LOOP;
END processEmps;
(Note: getAvgDeptSalary isn't a very good example, because you could also do that with SQL only, but it's just an example)

Very simple. A function in the WHERE clause which uses the procedure parameter pDepartmentId. What would you expect how the code/SQL is executed?

Do you expect the code is executed in the following order?
  1. Procedure processEmps is called
  2. Function getAvgDeptSalary gets executed by the PL/SQL engine, because the PL/SQL engine has already all input parameters for the function call. No values from the query are needed. The result gets stored into an internal temporary bind variable.
  3. Context switch to the SQL engine which executes the query on EMPLOYEES, restricted to SALARIES greater than the value in internal temporary bind variable.
Sorry you are wrong!

The hole SQL statement is handed over to the SQL engine, which then does a call to the getAvgDeptSalary function. That could be one time if you are lucky and the optimizer is clever enough, but it could also be for each row which is processed by the query!!! So it's the same processing as already described in my Caution when using PL/SQL functions in a SQL statement! You can also easily identify that behavior by yourself, because there are some restrictions in the usage of function calls in the WHERE clause:
  • You can only use public functions.
  • You can't use the non-positional syntax (at least in < 11g) for the function parameters.
That's because the SQL engine can only use public PL/SQL functions and can't handle the non-positional syntax for parameters.

So if you have somewhere in your code such function calls (like the V or NV functions in Oracle APEX), be aware that this could be a performance bottleneck! Do the function call before the SQL statement and use a variable to restrict the query.

Labels: , , ,


« ... Read full posting ... »

Lock conflicts with Automatic Row Processing (DML)

Oracle APEX 3.0 contains a nice new feature you should be aware of. There is a new substitution variable APEX_DML_LOCK_WAIT_TIME which you can use to define how the behavior of the "Automatic Row Processing (DML)" and ApplyMRU/D processes should be in case if the processed row is locked.

With the current setting APEX will wait forever until the row gets unlocked. The bad think about that is that users don't really wait long, they will press the stop button of the browser and submit the changes again and again. And everytime a new database connection from the connection pool is consumed and never released. Probably that would be an interesting denial of service attack vector, but that's a different story.

When can such a locking situation occur?

For example if you have a database where you also have an Oracle Forms application to access the same data, or any other client/server application. Because it's quite common for such applications, that they have a pessimistic locking strategy which means that they lock the row as soon as the users starts to change something. APEX and most web applications use an optimistic locking strategy.

Locks can also exist for a longer time if you have long running batch jobs or something similar which are not immediately committing there changes.

What setting should I use?

I would suggest to set the new substitution value to 0 in every application you create. Independent if you have the above scenario. A setting of 0 will immediately raise an error if the row is locked.

Other options can be found in the online documentation in the chapter About DML Lockings. More background information can be found in the related OTN thread.

Labels: , , ,


« ... Read full posting ... »

Slightly different behavior of $x in Oracle APEX 3.0

Just noticed a slightly different behavior of $x in Oracle APEX 3.0.

Probably many of you just use it to pass the id-string of an element (eg. $x("P4_TEST")) to this function to get the object of this field/div/... id, but you can also call it with an object and in that case the function will just return the object which has been passed in.

You may ask when do you need that? You need it if you write more generic JavaScript code where you have for example a function with the following example code
function getWhatEver(pField)
{
var vField = $x(pField);
// do what ever we want with vField
};

If the caller has already the field object, then he just can pass it in and the function doesn't have to do another lookup for the field
getWhatEver(vFieldVariable);
If the caller doesn't have one, he can still call it with the id string
getWhatEver("P4_TEST");
and the $x function will do the necessary lookup.

The above described behavior still works for objects of node type 1 (Node.ELEMENTNODE), but with Oracle APEX 3.0 it doesn't work if you pass in for example the window object, in that case the $x function will return false.

I had a function which can add/register events (eg. onkeypress, ...) to each object, but in APEX 3.0 it failed when called with the window object.

So just be aware of this changed behavior!

Labels: , , ,


« ... Read full posting ... »

Incomplete/Broken HTML output

A few days ago an ApexLib user from Norway contacted me and told me that the framework doesn't work and he is getting JavaScript errors.

I looked at the provided HTML output and I was scratching my head, because the output looked really strange and I couldn't really come of with a good reason why the JavaScript code was broken. Another wired thing was that it worked sometimes for the page and sometimes not, the error was depending on the data which was displayed!
apexlib.field.addField("P4_REGION_ID", [...]
apexlib.field.ddField("P4_COUNTRY_ID", [...]

In the above example, the "a" of addField was missing, but in the previous statement it was there. So no programming error.

After some investigation I found the thread strange things happening: broken html in output on the OTN Forum.

Arie gave me a good tip and as soon as the patch was installed, everything worked as expected.

I write this blog posting, because yesterday I read that another user on the OTN forum had the same problem and I suspect that most users ignore the post installation steps of the APEX installation. So that's a good chance to verify if you have installed the "PL/SQL Web Tookit Patch". That can save you a lot of time looking for an error which isn't really one.

Labels: , , ,


« ... Read full posting ... »

Caution when using PL/SQL functions in a SQL statement

Be cautious if you use PL/SQL functions/packages in your SQL statements, especially in the Where-Clause!

Why?

Because the function is probably called more often than you think it is! If you don't want to read the hole article, scroll down and check the APEX impact.


An example

Let's create the following simple function.
CREATE OR REPLACE FUNCTION getValue
( pValue IN NUMBER
)
RETURN NUMBER
IS
BEGIN
DBMS_Output.put_line
( 'called getValue with '||pValue||' at '||
TO_CHAR(SYSDATE, 'HH24:MI:SS')
);
RETURN pValue;
END getValue;
And now look at the following SQL Statement where we call our new function with a constant value.
SELECT COUNT(*)
FROM EMPLOYEES
WHERE SALARY = getValue(1)
;
How often do you think is the function called?

  • One time because it always uses the same value as parameter?
  • For each row which is checked by the query engine?
  • Some number between one time and for all rows?
Check the DBMS_Output.

If you have bet your money on For each row which is checked by the query engine, then you are the winner! It's called 107 times! As often as we have rows in the table.

If we change the query to
SELECT COUNT(*)
FROM EMPLOYEES
WHERE EMPLOYEE_ID > getValue(1)
;
How often to you think it is called? You have the same choice as before.

Check the DBMS_Output.

It's just called one time! What is the difference? In our second example the optimizer is using the EMP_EMP_ID_PK index and in that case as Tom Kyte explained me

The optimizer gets the start/stop range (the function might be called twice actually) and then it range scans with the constants.


So what's the deal all about it?

Keep in mind the performance issue when you have a function which is selecting against other tables and you use such a function in a where-clause, where 1.000's of records are processed!

Possible solutions?

You can change the query in the following way. The optimizer then knows that is ok when he executes the query just one time. So called scalar subquery caching, which works with all DB versions. Checkout AskTom about that term.
SELECT COUNT(*)
FROM EMPLOYEES
WHERE SALARY = (SELECT getValue(1) FROM DUAL)
;
Or you take a look at the DETERMINISTIC clause which can specified when creating a function or a package functions. What does it do? It's a hint for the optimizer to indicate that the function returns the same result value whenever it is called with the same values for its arguments. But, as noted by Tom Kyte

10gr2 supports deterministic as an optimization in SQL for the first time. Prior to 10gr2 - deterministic was all about function based indexes only - the SQL engine ignored it.

So only if you have a 10.2.x database, using DETERMINISTIC will give you a speed up of your query. Use the above solution instead.

But let's change our function and see what we get now.
CREATE OR REPLACE FUNCTION getValue
( pValue IN NUMBER
)
RETURN NUMBER DETERMINISTIC
IS
BEGIN
DBMS_Output.put_line
( 'called getValue with '||pValue||' at '||
TO_CHAR(SYSDATE, 'HH24:MI:SS')
);
RETURN pValue;
END getValue;
Run the first query again and you will see that the function is called just once!
Try the following SQL statement.
SELECT COUNT(*)
FROM EMPLOYEES
WHERE SALARY = getValue(SALARY)
;
How often do you think it is called? It's just called as often as there are different salaries in the table. With the old version of the function is called for each row again.

I know that the Oracle documentation about DETERMINISTIC says
Do not specify this clause to define a function that uses package variables or that accesses the database in any way that might affect the return result of the function.

Which I think is basically to see in relation to the function based index for which this "hint" has been introduced. From my observation, if you have such a function call in several SQL statements which are called after each other (eg in a anonymous pl/sql block), the function is executed again for each SQL statement. It's just a hint for the optimizer during execution of the current statement.

DON'T USE DETERMINISTIC if your function is changing some global variables (eg increase a counter) or doing DML and you expect that the function is called for each row!

And how is that all related to APEX?

Are you using the V or NV function in your SQL statements? In APEX 2.0 the V function isn't wrapped (in 2.2 it is) and I don't see that the DETERMINISTIC is used in the code... It's just memory processing they do in there, but if you call it for 1.000's of records...

Always use bind variables instead! Only use the V function in your packages, but never use them in your report SQL statements.

I have done a posting on OTN about speeding up the V function. Stay tuned.

UPDATE: See my posting Drop in replacement for V and NV function which contains a wrapper for the existing functions.

Labels: , , ,


« ... Read full posting ... »

Referencing non existing APEX items

Did you know that when you reference a non existing APEX item in your SQL statements or PL/SQL code, that you are not getting a runtime error? APEX will just return NULL in such a case!


It doesn't matter if you reference it with the bind variable- (eg :P8_TEST), V or NV function- (eg V('P8_TEST') ) or substitution- (eg. &P8_TEST.) syntax.

Just be aware of this behavior!

Labels:


« ... Read full posting ... »

APEX items and implicit type conversion

Be aware when using bind variables or the V function to reference a APEX item in your SQL statements or your PL/SQL code that APEX/Oracle always stores this values as VARCHAR2's in its internal arrays!


So each time you reference an item with :YOUR_ITEM or V('YOUR_ITEM') the SQL/PL-Sql engine does a implicit data type conversion.

Don't rely on implicit data type conversion as the Oracle manual already says!

To ensure your program does exactly what you expect, use explicit conversions wherever possible.

Maybe it will work most of the time, but I would suggest to use the NV function to get the value of numeric items or use TO_NUMBER, TO_DATE, ... around your bind variables eg. TO_NUMBER(:YOUR_ITEM).

For details see the Oracle manuals:

Labels: ,


« ... Read full posting ... »