Showing posts with label Oracle. Show all posts
Showing posts with label Oracle. Show all posts

Saturday, 21 August 2010

Just another implementation of string splitting function in PL/SQL

Here are some of my implementation of string splitting function in PL/SQL.
It is something developers need often, and still can't believe there isn't a function that does something like this in oracle 10g...???

Some developers parse delimited text using substr(text,X,Y) for every token they need to use in their code…

My advice is: Don’t ever do this!!! Use some available tokenizer function!

I found several implementations on the internet, but those functions either does not support delimiter with length more than 1, either it does not return tokens that are NULL, or does not return table of varchar2 index by pls_integer ( what I needed), etc.

So I wrote it myself…

Anyway, here is my first implementation, written entirelly in PL/SQL:

CREATE OR REPLACE FUNCTION splitString(str VARCHAR2,delimit VARCHAR2) RETURN dbms_sql.Varchar2_Table IS
  
  inputString VARCHAR2(32000);
  delimiter VARCHAR2(32);                         

  delimiters dbms_sql.Number_Table;
  tokens dbms_sql.Varchar2_Table;

  array_index PLS_INTEGER := 1;
  pos PLS_INTEGER := 1;
  delimiter_pos PLS_INTEGER;

  delimiter_length PLS_INTEGER;
  inputString_length PLS_INTEGER;

BEGIN

  IF str IS NULL THEN
  RAISE_APPLICATION_ERROR(-20000,'str cannot be null!');
  END IF;
  
  IF delimit IS NULL OR delimit = '' THEN
  RAISE_APPLICATION_ERROR(-20000,'delimiter cannot be null or empty string!');
  END IF;

  inputString := str;
  delimiter := delimit;

  delimiter_length := length(delimiter);
  inputString_length := length(inputString);

  -- Prepare inputText for parsing
  IF substr(inputString,inputString_length - delimiter_length + 1,delimiter_length) != delimiter THEN
      inputString := inputString || delimiter;
  END IF;

  IF substr(inputString,1,delimiter_length) = delimiter THEN
      inputString := substr(inputString,delimiter_length + 1,inputString_length);
  END IF;
  ---------------------


  -- find delimiter occurrences in inputText
   LOOP
      delimiter_pos := instr(inputString,delimiter,pos);
      EXIT WHEN delimiter_pos = 0;
      delimiters(array_index) := delimiter_pos;
      array_index := array_index + 1;
      pos := delimiter_pos + delimiter_length;
   END LOOP;
  --------------------
  
  -- reset temp variables
  array_index := 1;
  pos := 1;
  ---------------------

  -- iterate through delimiters and create tokens
  FOR j IN delimiters.first..delimiters.last LOOP
      tokens(array_index) := substr(inputString,pos,delimiters(j)-pos);
      array_index := array_index + 1;
      pos := delimiters(j)+ delimiter_length;
  END LOOP;
  --------------------

  RETURN tokens;

END;
/
Function’s parameters are string that needs to be tokenized, and a delimiter ( that can have length greater than 1).

Yoy could enchance it by setting


TOKENS     DBMS_SQL.VARCHAR2_TABLE;

to

TYPE t IS TABLE OF varchar2(32000) INDEX BY PLS_INTEGER;
TOKENS t;

if  you are dealing with tokens of length > 2000.
Also, these are case-sensitive functions. You can make it case-insensitive very easy...

Dejan  gave me an idea to write it using SQL.
So I did it, because his implementation using SQL to parse a string is cool:



CREATE OR REPLACE FUNCTION SPLITSTRING_USING_SQL(STR VARCHAR2, DELIMIT VARCHAR2)
  RETURN DBMS_SQL.VARCHAR2_TABLE IS

  INPUTSTRING    VARCHAR2(32000);
  INPUTDELIMITER VARCHAR2(32);

  TOKENS DBMS_SQL.VARCHAR2_TABLE;

  DELIMITER_LENGTH   NUMBER;
  INPUTSTRING_LENGTH NUMBER;

BEGIN

  IF STR IS NULL THEN
    RAISE_APPLICATION_ERROR(-20000, 'str cannot be null!');
  END IF;

  IF DELIMIT IS NULL OR DELIMIT = '' THEN
    RAISE_APPLICATION_ERROR(-20000,
                            'delimiter cannot be null or empty string!');
  END IF;

  INPUTSTRING    := STR;
  INPUTDELIMITER := DELIMIT;

  DELIMITER_LENGTH   := LENGTH(INPUTDELIMITER);
  INPUTSTRING_LENGTH := LENGTH(INPUTSTRING);

  -- Prepare inputText for parsing
  IF SUBSTR(INPUTSTRING,
            INPUTSTRING_LENGTH - DELIMITER_LENGTH + 1,
            DELIMITER_LENGTH) != INPUTDELIMITER THEN
    INPUTSTRING := INPUTSTRING || INPUTDELIMITER;
  END IF;

  IF SUBSTR(INPUTSTRING, 1, DELIMITER_LENGTH) != INPUTDELIMITER THEN
    INPUTSTRING := INPUTDELIMITER || INPUTSTRING;
  END IF;
  
  SELECT SUBSTR(INPUTTEXT,
                INDEKS + DELIMITER_LENGTH,
                NAREDNI - DELIMITER_LENGTH - INDEKS) TOKEN BULK COLLECT
    INTO TOKENS
    FROM (SELECT INDEKS,
                 LEAD(INDEKS) OVER(ORDER BY INDEKS) NAREDNI,
                 INPUTTEXT
            FROM (SELECT LEVEL INDEKS,
                         INPUTSTRING INPUTTEXT,
                         INPUTDELIMITER DELIMITER,
                         (CASE
                           WHEN SUBSTR(INPUTSTRING, LEVEL, DELIMITER_LENGTH) =
                                INPUTDELIMITER THEN
                            1
                           ELSE
                            0
                         END) IS_DELIMITER
                    FROM DUAL
                  CONNECT BY LEVEL <= LENGTH(INPUTSTRING))
           WHERE IS_DELIMITER = 1)
   WHERE NAREDNI IS NOT NULL;

  RETURN TOKENS;

END;
/
It’s basically very similar to his function.
The only difference is that unlike Dejan’s function, this one returns NULL tokens too…

You can test theese two functions easy:


declare 
  
  input VARCHAR2(32000) := 'one***two***three***four***five***six***seven***eight***nine***ten';
  delimiter varchar2(10) := '***';
  result dbms_sql.Varchar2_Table;
  
begin

  result := splitString(input,delimiter);
  --result := splitString_using_sql(input,delimiter);
  
  for i in result.first..result.last loop
      dbms_output.put_line(result(i));
  end loop;
                        
  
end;





Conclusion:
There are CERTAINLLY better ways to write this function, and these are just an example how this could be done.

This is one possible approach, to return an array of tokens. For me , probably the better way would be to create an Object that does something like StringTokenizer Java class. Not to return an array, but to provide a way to iterate through tokens using it’s hasMoreTokens() and nextToken() methods.
I think this is better approach if you are dealing with very large input strings and tokens. If you are dealing with small ones, then it’s OK to use one of my funtions I provided here, or any other similar to this one, that you can find on the internet…

If you intend to use one of these, I suggest  on using first one, because It is much faster than second one.

I didn’t do any optimizations ( which is obvious  ) because I was pleased with speed. Of course, you are welcome to do it yourself

as a matter of fact, I did some speed testing with input strings whose length is ~ 30000, and the first one was (much) faster than many  functions I found on the internet…

Thursday, 4 February 2010

Oblikujte novi Oracle Forms builder

Prenosim svoj novi tekst sa bloga baze-podataka.net
( http://www.baze-podataka.net/2010/02/04/oblikujte-novi-oracle-forms-builder/ )


Nedavno je na Oracle-ovom forumu  pokrenuta tema na kojoj možete predložiti šta bi bilo dobro da se doda u Oracle Forms.

http://forums.oracle.com/forums/thread.jspa?threadID=1021732&start=0&tstart=0

Na ovaj način je ljudima koji koriste ovaj alat je data sjajna prilika da oblikuju  narednu verziji Forms-a.
Naravno, neće se svaki predlog prihvatiti, ali vrijedi pokušati...

Lično, prve stvari koje su mi pale na pamet su

- dodavanje kalendarčića ( ovo trenutno radim preko Java binova, ali bi bilo puno bolje imati neki gotovi formsov objekat )
- poboljšanje editora PL/SQL-a ( trenutni editor je više nego smiješan. Čak kada razmislim - ne znam za gori )
- ugrađena podrška za webutil ( nepotrebno zakomplikovano )

- bolje odrađena podrška za slike ( slike importovane preko Image item-a su neprihvatljivo loše )

- bolje urađena podrška za kreiranje i importovanje Java binova ( nepotrebno zakomplikovano, bez ozbiljnog  modula u samom IDE-u koji bi developerima pomogao pri kreiranju binova )

- veća sloboda pri kreiranju i oblikovanju data blokova. ( Npr. da se može zadati upit na osnovu kojeg će se u run time-u izgenerisati  data blok ( ok, koji bi bio read-only ) . Npr. kao data grid koji imamo u BCB-u, .NET-u... .)

Naravno, ima još toga čime bi se trebalo pozabaviti u formsu, kao što je npr. debugger, VCS , prelaženje sa aplet aplikacija  na ajax aplikacije , standardizacija IDE-a itd i još dosta dosta toga...

Dakle, ko ima ideje - neka predloži...

Friday, 27 November 2009

Oracle OpenScript


Nema, Oracle je zaista Interesantan...
Ono što on napravi MORA ostaviti utisak na vas!
Makar na mene ostavlja...

Nekad cete biti zaprepašceni kako je Oracle nešto loše i/ili nestandardno uradio ( npr. Oracle-ova konzola, code editor u Oracle forms-u, oracle designer, odredene specifičnosti PL/SQL-a… i još mnogo toga) , a nekad ( uglavnom ) cete biti zapanjeni kvalitetom uradenog ( npr. Oracle Discoverer , ADF , oracle Reports, APEX , web util ... i još  mnogo toga )
E, postoji jedan alat koji je posljednji u nizu ostavio više nego pozitivan utisak na mene.
Njegovo ime je Oracle OpenScript.



Svi koji rade na razvoju Oracle Forms ili klasicnih web aplikacija ce biti više nego oduševljeni onim što ovaj alat ima da ponudi.

Rijec je o Eclipse-based IDE-u u kojem možete kreirati skriptove za automatizovano testiranje vaših aplikacija.


Ja ga još nisam detaljno ispitao, ali i sa ovoliko malim iskustvom sa Oracle openScript-om oduševljeno tvrdim da je ovo jedna nova stavka mome spisku must-have alata za razvoj forms i web aplikacija.
I upravo je stigao u savršenom trenutku, što se mene tice!

Kreiranje ogromnih formi je upravo postao mnogo lakši posao ?

E kad se samo sjetim dugometražnih unosa podataka i beskonacnih pozivanja novih i novih formi i LOV-ova da bi dobio samo jednu logicku cjelinu unutar baze novog IS-a zarad testiranja uradenog…
Pa ako nešto ne valja, ispraviš to i sve iz pocetka…

Kako se radi sa Oracle openScriptom?

Ono što sam ja do sada vidjeo – jako jednostavno!

Kreirajte script za automatizovano testiranje vaše aplikacije,



i dobicete novi prayan script sa defaultnim cjelinama :

-    initialize
-    run
-    finish



Rijec je ustvari o vizuelnoj prezentaciji java coda koji se generiše u pozadini, tj. Na jezicku “Java code”




The OpenScript Tree View scripting interface provides a graphical representation of the test script. Multiple script windows can actually be open at the same time. Within each script window, the Tree View is broken down into 3 main script sections:
•    Initialize: For script commands that only execute once on the first iteration
•    Run: Main body of the script for commands that will run on every iteration
•    Finish: For script commands that only execute once on the last iteration
Within each section, script Steps and Navigation nodes can be created automatically during script recording or manually through the Tree View user interface. Additional script commands will also be represented as nodes in Tree View including test cases, data inputs, log messages, etc. Each Tree View node has a corresponding representation in the Java Code View.



A kako se to Javin kod generiše?

Pa, po onome što sam vidio , najjednostavnije npr. klikom na dugme “record” .
Kada kliknemo na ovo dugme, otvorice nam se defaultni browser ( ovo možete promjeniti u podešavanjima unutar samog okruženja ) i Oracle openScript ce na osnovu vašeg djelovanja generisati script ( Java code ) koji ce biti code-prezentacija onoga što ste vi uradili prilikom testiranja.
Dakle, IDE sve pamti, I upravo ce , kada kliknete na dugme “playback” sve sam ponovo uraditi.
Sve adrese koje upišete u adres bar , sve na šta kliknete, koje sve popup ili nove prozore otvorite, koji sve prozori preuzmu fokus, sve ce se “pamtiti” u kodu kreiranjem poziva prema odgovarajucim funkcijama API-ja koji Oracle OpsenScript koristi.

Sjajna stvar!

Ovo je, naravno, najlakši nacin za generisanje skripta.
Postoji i rucno pisanje koda, koje je sigurno naprednije i mocnije, i mnoge druge funkcionalnosti koje IDE nudi, ali kažem – nisam ga mnogo koristio da bih mogao prenijeti tips and tricks…

U svakom slucaju – u pitanju je stvarcica kojoj cu sigurno pružiti šansu. Još jedna od onih iz Oracle-ovih laboratorija koja vas ostavi bez daha…


Dakle, ko je zainteresovan da isproba, i olakša sebi život, download strana je:
http://www.oracle.com/technology/software/products/app-testing/index.html

Ko želi koristiti Oracle openScript sa Oracle Forms developerom , evo i jedan lijep link sa kratkim uvodom u tu materiju:

http://www.scl.com/software-quality/software-quality-resources/testing-oracle-forms-with-openscript


Cujemo se, nadam se , uskoro na ovu temu ponovo...  ;-)

Monday, 19 October 2009

Oracle ROWNUM

Na baze-podataka.net je izašao moj novi post, ovaj put posvećen priči o rownum-u u Oracle RDBMS-u.

Tema može biti interesantna ljudima koji ranije nisu detaljnije čitali o ovoj pseudo koloni.
Objašnjeno je  njeno pravilno korišćenje u upitima , i skrenuta pažnja na neke česte zablude u vezi rownum-a...

Link: http://www.baze-podataka.net/2009/10/19/oracle-rownum/

Monday, 25 May 2009

SQL Developer , nebrušeni dijamant

Obožavam maj.
To je mjesec kada se u Crnoj Gori najviše praznuje.
Prvo dođe 1. maj pa onda i 21. maj , prije toga u aprilu i uskrs
i ako se “poklopi” da ovi dani padaju u četvrtak – petak , tu ukupno bude fin broj dana za odmaranje.

To je razlog što me dugo nije bilo sa novim tekstom. Praznovalo se, što ću :-)

Ako se ovome doda da sam u maju bio još i na ( zasluženom ) odmoru od ogromnog i iscrpljujućeg projekta – mogu reći da mi je ovaj maj bio poseban... :-)

Međutim, majski praznični dani su u Crnoj Gori, na žalost, završeni :-(
Ali nije ni to loše. Ja sam jedan od onih koji obožavaju svoj posao.
A tu su i novi tekstovi na devtalks-u …

Prije neki dan mi pade na pamet jedan duži tekst koji sam posvetio recenziji IDE-ova za rad sa Oracle-om, pisanju koda u PL/SQL-u, upita u SQL-u i slično, a koji nikada nisam objavio.
Dakle, o alatima koji su u ponudi na tržištu, i moje impresije o istima.
Konkretno – radi se o “PLSQL Developer”-u , “Toad”-u , “SQL Developer”-u i “SQL Manager 2007 Lite for Oracle”.
Ja u principu nisam baš totalno zadovoljan alatima ove vrste za rad sa Oracle-om i ovo je upravo jedna kategorija IDE-a koje sam vrlo često mjenjao tokom rada sa pomenutom bazom ne bih li našao nešto što mi u potpunosti odgovara.

Ovdje ću prenijeti samo dio teksta, i to onaj koji je posvećen Oracle-ovom SQLDeveloper-u.

Dakle, ovako sam tada opisao ovaj alat:


SQL Developer



Ako pričamo o konkurenciji Toad-u, onda moramo na prvo mjesto staviti program koji nam dolazi pravo iz Oracle-a a koji je ranije bio poznat pod nazivom Raptor: SQL Developer.
Zaista svjetlo na kraju tunela, i pravo osvježenje!



Ovo je nešto što, po meni, najviše liči na jedan pravi alat za rad sa bazom podataka i razvoj aplikacija, kada je u pitanju Oracle.
To što je pisan u Javi je u jednoj mjeri dobra stvar, a u najvećoj mjeri jako loša.
Upravo je moja najveća zamjerka kod ovog programa uperena ka njegovoj brzini. Ustvari ne ka brzini izvršavanja naredbi toliko - koliko na brzinu renderovanja njegovog izgleda i brzinu jave u domenu GUI-ja inače.
Znamo da Java baš i nije svjetski prvak u brzini kreiranja GUI objekata. E , tu ova mana dolazi do izražaja.
Mislim da su momci iz Oracle-a mogli ovaj aspekt malo bolje uraditi. Pravi primjer brzog IDE-a pisanog u Javi kod kojeg nikada nemamo ovaj problem je npr. NetBeans ili Eclipse.
Često mi se desi da nakon dugog rada u nekom drugom programu, kliknem da se vratim na SQL Developer, a onda moram da sačekam ko zna koliko ( dragocjenog ) vremena da mi se prikaže program sa svim elementima i trenutnim stanjem.
Inače, ovo je možda jedina ozbiljnija zamjerka na ovaj program.
Program ima veoma dobar code completion , ima podršku za CVS i subversion, stablo je veoma lijepo urađeno, pregledno je i brzo.
Ima skoro sve elemente koje editor jednog savremenog IDE-a treba da ima.

Pristup tabelama je veoma jednostavan i brz:
Jednim klikom na neku tabelu nam se odmah otvara novi prozor sa svim informacijama po tabovima za odabranu tabelu.

Tabela za prikaz podataka bi mogla biti puno ljepša , a njene ćelije malo većih dimenzija.

Još jedna dobra stvar kod ovog programa je ta da ne moramo imati instaliran nikakav Oracle client kod sebe, jer za konekciju ne koristi tnsnames.ora već JDBC drajvere.

SQL Developer sada zaista zaslužuje da mu se da šansa.

Savjet:
Svim korisnicima savjetujem da prije početka obavezno urade sljedeće:

Tools -> Preferences -> Database -> Object viewer Parameters i štrikirajte “Automatically freeze object viewer windows” jer će se u protivnom svaka tabela na koju kliknemo jednom otvarati uvijek u jednom istom prozoru. Sada će se svaka tabela otvarati u posebnom prozoru.


Da , to je nešto što bih ranije rekao za ovaj alat, nakon nekoliko nedjelja rada u njemu i to u NE kritičnim situacijama, kada se mogu tolerisati određene gluposti koje IDE može izazvati.
Tada mi je ovaj program zaista bio pravo osvježenje jer je izgledao oprilike onako kako sam ja zamišljao da bi jedan IDE za rad sa Oracle-om ( za developere, naravno ) i trebao izgledati.
Ono što bih sada rekao za ovaj IDE je da ga se bar još neko vrijeme zaobilazi u širokom luku!
On je OK da se kući koristi i za učenje, ali ako se odlučite za njega na nekom ozbiljnijem projekrtu - uvijek treba imati pored sebe i jedan od dokazanih alata.

Zašto sam promjenio mišljenje? Pa kao prvo zato što sa ovim alatom nikada ne znaš na čemu si. Recimo da smo prepravili neku funkciju, paket, proceduru...
Nakon kompajliranja istih uopšte nećemo znati da li je kompajliranje uspješno obavljeno, da li je novi objekat validan , u čemu je problem ako problem postoji ( ne prikaže se lijepo poruka kao u npr. Toad-u )…

Evo još jedan primjer: Dešavaće vam se nekada da će program sam od sebe početi prikazivati neki view sa uduplanim kolonama, dok je u drugim alatima taj pogled sasvim OK. A onda ti ako nemaš na produkcionoj lokaciji još neki alat nećeš moći ništa dalje raditi oko pomenutog pogleda...

Ako program ( kojem inače ne treba instalacija ) iskopiramo na neki drugi računar i pokušamo ga pokrenuti – tu nastaju tek posebne situacije i blokiranja računara...
O fantomskom brisanju ili dodavanju znaka tačka-zarez ( ; ) na kraju kodova koje želimo iskompajlirati – ni da ne pričam!

Sve u svemu – SQL Developer je zaista alat kojeg jedna tanka linija dijeli od odličnog alata i vjerovatno će to uskoro i postati, kada se isprave određene nebuloze koje postoje u njemu. Zaista je sjajno zamišljen.
Mislim da Oracle mora sebi priuštiti jedan ovakav, ali bug-free i price-free alat po svaku cijenu.

E, da , za kraj: jedva čekam maj 2010-e. :-)

Friday, 27 March 2009

Easy_Logger for Oracle - Log every insert, update or delete for a table , with details

When it comes to client's demands when creating some IS or designing a DB, very often there's a need to have a complete log of all actions on some table containing important data.
I received a few such demands myself...

Something like this isn't so hard to make it yourself.

We could easily write a
before insert or update or delete trigger and iterate through all the columns saving all old and new values into some log table.
But what if we have many tables that needs such log? Writing all of these triggers would take a quite time...
And what happens when we alter some of these tables?

That is why I created "Easy_Logger".
Thanks to Easy_Logger we can easily create and maintain logging triggers.

Easy_logger is a PL/SQL package , so it can be applied only to Oracle.
It is written in Oracle 10g. I didn't test it on any other version...

So, how do we use Easy_Logger?

First of all, you should run this script:

instal_EL_prerequisites.sql

It will create a table called "EL" ( as Easy Logger ) which will contain all of our logs.
It has 6 columns:

EL_ID - autoincrementing ID , primary key
EL_TABLE - Table name for which the log is created
EL_ACTION - Which action was logged ( insert, update or delete )
EL_LOG - The log itself containing all the old and/or new values in a record
EL_USER - User name which commited action
EL_DATE - When was log created

If this script ended without errors, you can now download Easy_Logger package itself and apply it into your database:

Package declaration
Package body


If everything went well, and without errors, you can now start creating a logging trigger for any table you wish.
I will explain now how to do this:

When creating an Easy_logging trigger for some table, you need to specify some parameters , that are part of a record EL_PREFERENCES:

it looks like this:

TYPE EL_PREFERENCES IS RECORD (
table_name varchar2(64),
create_AFTER_trigger BOOLEAN := true,
on_insert BOOLEAN := true,
on_update BOOLEAN := true,
on_delete BOOLEAN := true
);

so, if you want to create an AFTER [{INSERT},{UPDATE},{DELETE}] TRIGGER, you would set "create_AFTER_trigger" variable to TRUE ( else, if you would like to create a BEFORE [{INSERT},{UPDATE},{DELETE}] TRIGGER, you would set "create_AFTER_trigger" variable to FALSE) .
"Table_name" variable holds information about table's name for which you want to create a trigger,
and "on_insert" , "on_update" and "on_delete" simply tells Easy_logger on which action should a trigger fire.
After you set all of this variables, you need to call a procedure called EASY_LOGGER.CREATE_TRIGGER() by sending this PL/SQL record to it...




EXAMPLE:

if we want to make a trigger that fires on after inserting or deleting a record in a table called MY_TABLE, we would execute following code:

declare
preferences EASY_LOGGER.EL_PREFERENCES;
begin
preferences.table_name := 'MY_TABLE';
preferences.create_AFTER_trigger := true;
preferences.on_insert := true;
preferences.on_update := false;
preferences.on_delete := true;
EASY_LOGGER.CREATE_TRIGGER(preferences); <-- this is the procedure for creating a trigger!
end;

or just call

exec EASY_LOGGER.CREATE_TRIGGER('MY_TABLE',true,true,false,true);

(notice that arguments for this procedure are exactly in the same order as variables in EL_PREFERENCES record)

and a code for creating a logging trigger will generate in dbms_output, so don't forget to set serveroutput on!

All that there is left for you to do is to execute generated code, and you'll have your logging trigger for MY_TABLE table created.

For those who need generated code as a returning value, and not as dbms_output output, there is a function called get_trigger_ddl which has no input parameters.
It returns last generated trigger's  DDL .

You can call it like this:

declare
your_variable clob;
begin
EASY_LOGGER.CREATE_TRIGGER('MY_TABLE',true,true,true,true);
your_variable := EASY_LOGGER.get_trigger_ddl();
...  -- do whatever you like with generated code...
end;

That's it!
Every action specified when creating logging trigger will be logged in EL table.
I hope you'll like it...
You are free to report any bug, or suggest any good idea for me to implement in order to make Easy_logger better...

Friday, 12 September 2008

Data block wizard problem: cannot select all available columns

I had a problem few days ago with oracle forms builder,  and unfortunately could not find answer on the net why is it happening…
I created a view and needed to make a data block on my canvas, but data block wizard refused to let me choose all available columns in that view:

Let’s start from the beginning.
Let’s say we have a table called test:

Let’s make some (stupid) view of it. Let’s say we need a view that looks like this:
Select id, first , second, first || second as "FIRST AND SECOND TOGETHER" from test

Lets call it test_view.
So, I wrote:
Create view test_view as Select id, first , second, first || second as "FIRST AND SECOND TOGETHER" from test
And I couldn’t use column "FIRST AND SECOND TOGETHER" !!!???

This was the first time this happened to me, and I was working with view in data block wizards before…
After a while I finally found out why this was happening.
It seems that oracle forms builder  won’t let you select column that was named as “” in create view statement.
It is totally legal to say:
 Create view test_view as
Select id, first , second, first || second as "FIRST AND SECOND TOGETHER" from test
And it will work just fine, but you won’t be able to use it in oracle forms builder.
So, at the end, I  was foced to name my column FIRST_AND_SECOND_TOGETHER ( one word!!!) :
CREATE OR REPLACE VIEW TEST_VIEW
AS
select id , first, second , first || second as FIRST_AND_SECOND_TOGETHER from test;
and it worked!!!
I hope this will help someone…




Friday, 25 July 2008

Quick tip 3: How to get List index in oracle forms builder

As i can see, many people have this problem. They have a hard time to get index of an item selected in some list.
As I can tell, there isn’t a function like GET_LIST_INDEX() or something like that.
I had this problem myself few times before, and then I wrote this PL/SQL function:

FUNCTION getListIndex (LIST IN VARCHAR2, VAL IN VARCHAR2) RETURN INTEGER IS
BEGIN
IF To_Number(Get_List_Element_Count(LIST))>0 THEN
FOR i IN 1..To_Number(Get_List_Element_Count(LIST)) LOOP
IF Get_List_Element_Value(LIST,i) = VAL THEN
Return i;
END IF;
END LOOP;
ELSE
RETURN -1;
END IF;
END;


And to find out which index you selected by clicking on the list, call
getListIndex(‘blockX.listX , :blockX.listX);
This will return selected index, and -1 if the list is empty…
For example, to delete something from some list you just cdouble-clicked, call:

-- on WHEN-MOUSE-DOUBLECLICK trigger:
...
DELETE_LIST_ELEMENT('block3.list4',getListIndex('block3.list4',:block3.list4));
...

Sunday, 13 July 2008

Creating and using Java beans in Oracle Forms builder

Probably anyone who uses Oracle Forms Builder, at some point found himself with a certain problem that is very hard to fix using Oracle Forms Builder only, although it gives prety much everything you need to build a database application.
On the other hand , large number of those who managed to solve the problem weren’t even aware of a fact that they were able to solve that ’large’ and unusual problem by using Java beans, which can be used in Oracle Forms Builder.
Not to mention that many developers don’t even know about this functionality of Forms Builder that enables us to use Java code in our Oracle Forms application, and those who do know about it don’t know HOW to do it!
What I now plan to do is to show you how you can create and use some simple java bean in your Oracle Forms application.
These examples are far from usefull and complex but it will help you understand how to make a java bean and then you can create very usefull and complexe modules using almost complete power of Java...
I use Oracle 10g , and Developer suite 10g , and that means that we must use 1.4 version of java while building our bean.
Let’s open Eclipse and create new Java Project. Let’s call it „MyBean“ , and let’s create one Java class called „FirstBean“. For now, we have something like this:


The easiest way of creating a java bean that we can use in oracle forms builder, is to extend Vbean class. Vbean is located in frmall.jar. You can find it in %ORACLE_HOME%\forms\java on windows. ( for example, I have it on location C:\oracle\DevSuite\forms\java )
In order to use it, open project -> properties in eclipse , and under „java build path“ click on the Libraries tab , and then select frmall.jar by clicking on the „Add external jars“ button.


I mentioned before that we must use 1.4 compiler compliance level , so select it from drop down list, under „Java compiler“.


Click apply .
I will make a bean that we can use to:
- Get our own IP address
- Switch letters case of some string to upper case
- and to show input dialog for a user to enter some string and retrieve that string.
These examples are more than trivial , but they will help you understand a logic of building java beans that you can use in oracle forms builder.
You will soon see that we communicate with java beans by setting and getting some custom properties. all this is done by the use of the getPropery and setPropety methods defined in the Iview interface. Each property is created and stored within the oracle.forms.properties.ID class.
Let’s make 5 of it:


We will use I_TEXT to set an input dialog text, IP to retrieve ip address , SET_STRING to set a string for which we change letters case , SHOW_INPUT to say a java bean that we want to show input dialog, and UPPER_CASE to say a java bean that we want to retrieve (upper cased) string that we sent earlier.
So, the only two things we need to set before getting the result from java bean are I_TEXT ( text to be shown on input dialog) and SET_STRING ( the string that is about to be upper cased ).
In order to set it, we must use setter setProperty() :


and later when we call SET_CUSTOM_PROPERTY in PL/SQL we will send it’s value.
example:
If we have a BEAN_AREA in oracle forms called BLOCK4.BEAN_AREA11 , and want to set I_TEXT ( input dialog text ) to be : „Please insert a value:“ , we would call
Set_Custom_Property('BLOCK4.BEAN_AREA11',1, 'I_TEXT', ’Please insert a value:’);
The other three ID classes are used to get a value ( remember? : IP , upper case string, and input dialog entry )

and with PL/SQL’s function GET_CUSTOM_PROPERTY we are able to get these properties.

example:
If we have a BEAN_AREA in oracle forms called BLOCK4.BEAN_AREA11 , and want to get and show user’s entry from the input dialog into the :BLOCK4.TEXT_ITEM10 , we would get it by calling:
:BLOCK4.TEXT_ITEM10:=GET_CUSTOM_PROPERTY('BLOCK4.BEAN_AREA11',1,'SHOW_INPUT');
Here is the entire FirstBean.java file.
When we are finished writting a java bean, let’s export it as a .jar file named „mybean.jar“.
In eclipse, right click on MyBean project, and select „Export“. Follow the wizzard .


Copy the .jar file you exported into %ORACLE_HOME%\forms\java folder ( in the same folder where frmall.jar is located ).
Update %ORACLE_HOME%\forms\server\formsweb.cfg with „mybean.jar“ entry:


in the registry editor update FORMS_BUILDER_CLASSPATH variable :


Start OC4J instance ( START -> Oracle developer suite -> Forms Developer -> Srart OC4J instance ) .
Start Forms builder.
and on the canvas drop BEAN_AREA. Set it’s Implementation Class property to
me.tcom.darko.bean.FirstBean


and start using it.
Here is the following code for our three functionalities:
to retrieve IP address:
:BLOCK4.TEXT_ITEM10:=GET_CUSTOM_PROPERTY('BLOCK4.BEAN_AREA11',1,'IP');
(notice: we are not setting anything in order to get this result )
to change letters case of some string to upper case:
Set_Custom_Property('BLOCK4.BEAN_AREA11',1, 'SET_STRING',:BLOCK4.TEXT_ITEM14);
:BLOCK4.TEXT_ITEM10:=GET_CUSTOM_PROPERTY('BLOCK4.BEAN_AREA11',1,'UPPER_CASE');
(notice: in order to get upper cased string, we need to set it first )

and to show input dialog to user , and retrieve user’s entry:
Set_Custom_Property('BLOCK4.BEAN_AREA11',1, 'I_TEXT',:BLOCK4.TEXT_ITEM6);
:BLOCK4.TEXT_ITEM10:=GET_CUSTOM_PROPERTY('BLOCK4.BEAN_AREA11',1,'SHOW_INPUT');
( notice: again, we need to set I_TEXT first in order to show input dialog )

Here
is complete code ( mybean.jar , FirstBean.java and MYBEAN_FORM.fmb ).

Java beans in oracle forms builder can really be powerful. For many things that you cannot do in Forms builder there is JAVA.
For example you can make java swing application, integrate it into java bean and call it from within oracle forms and many more…
Also, you can register events in oracle forms builder of that swing application and use it , and many more, but some other time about that…