07 February 2014

Triggering and Handling a Custom Event in APEX

On one of the pages there was a need to refresh a report region when a node in an APEX Tree was clicked. As far as I know there is no built-in method to create a Dynamic Action to a node in an APEX Tree, so this might call for a Custom Event.
If there is a built-in method, please leave a comment :)

Trigger Custom Event

To trigger a Custom Event, change the "link" column in the APEX Tree Query to something like the following:

select ...
      ,'javascript:apex.event.trigger(document, "nodeClicked", "'
        ||value_from_table||'"); void(0);' as link
from ...
This will include a little bit of javascript in the anchor when the APEX Tree is generated which triggers the "nodeClicked" event passing the "value_from_table" that you want to pass in.
The "value_from_table" will be available in the Custom Event as the Data object.

Handling the Custom Event

To handle the Custom Event, follow the "Create Dynamic Action" wizard and fill in the following:

  • Event: Custom
  • Custom Event: nodeClicked
  • Selection Type: Dom Object
  • Dom Object: document
When you want to get the "value_from_table", you will need to reference
this.data;

In my case I needed the "value_from_table" and use "Set Value" as a TRUE action, and refresh a report.

Links

APEX Javascript documentation

04 December 2013

Invisible Not Null Column

Yesterday I attended John King (@royaltwit) session on Oracle 12c for developers. He gave an overview of all the goodies that are available to us as developers. The whole plugging and unplugging of database, though very cool and exiting, is most likely not very relevant to most developers.
When he discussed the possibility to have invisible columns in a table, it triggered the question: What happens when a NOT NULL column is made invisible? To see what would happen, I set up a small test case on my Oracle 12c database.
SQL> select banner
  2    from v$version
  3  /

BANNER
--------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE 12.1.0.1.0 Production
TNS for Linux: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production
First create a table, two columns - both NOT NULL, and some data.
SQL> create table t
  2  (id   number not null
  3  ,text varchar2(10) not null
  4  )
  5  /

Table created.

SQL> insert into t values (1, 'Hello')
  2  /

1 row created.

SQL> insert into t values (2, 'World')
  2  /

1 row created.

SQL> commit;

Commit complete.
Next to change the TEXT column to be invisible.
SQL> alter table t modify (text invisible)
  2  /

Table altered.

SQL> desc t
 Name        Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID        NOT NULL NUMBER

SQL> select * from t
  2  /

 ID
----------
  1
  2
The data that we entered is still there, or at least the ID values are still there.
So the column is now invisible, what if we try to add new data into it?
SQL> insert into t values (3)
  2  /
insert into t values (3)
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("SCOTT"."T"."TEXT")

Even though you can't see the column, the NOT NULL constraint is still enforced.
When you name the column explicitly, you can still do DML on it.
SQL> update t 
  2  set text = upper(text)
  3  /

2 rows updated.
But not like this
SQL> insert into t values (3, 'Goodbye');
insert into t values (3, 'Goodbye')
            *
ERROR at line 1:
ORA-00913: too many values
This following is still valid, and again shows that naming the columns in an INSERT statement is a good practice.
SQL> insert into t (id, text) values (3, 'Goodbye');

1 row created.

20 November 2013

APEX Tree based on Pipelined Table Function

Representing hierarchical data in an APEX Tree is fairly straight forward, the wizard to create a tree region assists you with that. But when you need to show data from multiple tables, you will need to provide your own query. In a previous blogpost I have written how to achieve that.
It is also possible to create a Pipelined Table Function which can be used a the basis of the APEX Tree. In this blogpost I will show you how to do that.

18 November 2013

PIVOT and UNPIVOT

The PIVOT and UNPIVOT operators were introduced in Oracle 11g and the other day I helped out a friend using these operators.
He wanted the data in the columns to be "shifted to the left". To explain a little more, take a look at the following data:
        ID V1    V2    V3    V4    V5
---------- ----- ----- ----- ----- -----
         1 a     b                 e
         2 aaa   bbbb  cccc
         3             a     b     e
         4 a           c           e
         5       b           d
Above is the data as it appeared in the table.
The requirement was to shift the data to the left like the data below:
        ID C1    C2    C3    C4    C5
---------- ----- ----- ----- ----- -----
         1 a     b     e
         2 aaa   bbbb  cccc
         3 a     b     e
         4 a     c     e
         5 b     d

The data in the columns is moved over one or more columns to the left.

15 November 2013

Tree with Checkboxes: Save the Data - JS Array to PL/SQL

In two previous blogposts I described a method to transform a regular APEX Tree component to a Tree component with checkboxes. The second blogpost described a way to retrieve the data from the database using JSON and AJAX and check the appropriate checkboxes. In this last part of the series on Tree with Checkboxes I will describe a method to save the checked values to the database.

25 September 2013

Oracle In-Memory Database

One of the big announcements of Oracle Open World 2013 is the Oracle Database In-Memory option. By simply "flipping the switch" the application will run faster than ever before.
From my understanding flipping the switch is making changes to some (not sure which) initialisation parameters.

Secret Sauce

What is the big deal with Oracle In-Memmory Database? Well, it is fast - really, really fast. DRAM is faster than Flash, and Flash is faster than disks.
Another big deal is the dual format in which the data is stored. The data is stored in a columnar and row fashion, both in memory. This means that analytical type queries can be answered by the columnar storage while other type of queries can be resolved using the row storage. And yes, the optimizer is aware of columnar storage as well.
Oracle takes care of storing the data in both formats, this is done completely transparent. It is simultaneously active and transactionally consistent. The secret sauce is the dual format storage, this is what it really makes it fast.
The columnar format of the data is memory only, the row format is stored in memory and persisted on disk, just as it is nowadays. In order to take full advantage of this you don't need to learn anything else - from a developer point of view.
During DML the affected data is marked as stale (in memory) thereby limiting the overhead. You can pick and choose which tables, partitions, columns you want to have in columnar format.

How does it differ from TimesTen?

How does it difer from TimesTen? Good Question. TimesTen is also an in memory database which has been around for a number of years. TimesTen is a more specialized approach to solve a particular business problem. The Oracle Database In-Memory Option does not tackle a particular problem, it works for the database as a whole.

Links

Oracle Database In-Memory Option press release

17 September 2013

Tree with Checkboxes - Pre-Select Data with JSON

After you have modified the standard APEX tree to a tree with checkboxes (see this blogpost) you will probably need to find a way to load data from the database and show the values previously checked by the user.
In this blogpost I will show you how to load the data from the database using an AJAX-call and check the appropriate checkboxes in the tree.
The method described here retrieves the data uses the APEX_UTIL.JSON_FROM_SQL procedure and an AJAX call. This method can be used for many more things besides populating a Tree with checkboxes :)