20. Dezember 2006

Undo

Daten aus der Datenbank abfragen und ändern ist in Forms relativ einfach. Aber was ist, wenn der Anwender einen einfachen Undo auf seine Änderungen machen will?

Einfach eine neue Abfrage starten ist der einfachste Weg. Beachtet werden muss:

- in einem Multi-Record-Block muss man sich nach der Abfrage wieder auf dem aktuellen Datensatz positionieren
- wenn die Abfrage durch eine ENTER-QUERY-Selektion geschah kann man nicht zu dem Datensatz springen, da die Abfragemenge unterschiedlich gross ist.

Man muss also eine andere Technik verwenden.

Die Lösung ist diese Funktion. Alle Datenbank-Felder bekommen ihren alten Wert zurück:


PROCEDURE Undo IS
V_Block VARCHAR2 (30) := :SYSTEM.CURSOR_BLOCK;
V_Field VARCHAR2 (61);
V_Item VARCHAR2 (61);
BEGIN
Validate (Item_Scope);
IF :SYSTEM.RECORD_STATUS = 'CHANGED' THEN
V_Field := Get_Block_Property (V_Block, FIRST_ITEM);
V_Item := V_Block || '.' || V_Field;
WHILE V_Field IS NOT NULL
LOOP
IF Get_Item_Property (V_Item, ITEM_TYPE)
IN ('DISPLAY ITEM', 'CHECKBOX', 'LIST',
'RADIO GROUP', 'TEXT ITEM')
AND Get_Item_Property (V_Item, BASE_TABLE) = 'TRUE'
THEN
COPY (Get_Item_Property (V_Item, DATABASE_VALUE),
V_Item);
END IF;
V_Field := Get_Item_Property (V_Item, NextItem);
V_Item := V_Block || '.' || V_Field;
END LOOP;
END IF;
END;


Best practice wäre, wenn man diesen Undo vom Menü aus starten könnte (z.B. Bearbeiten - UNDO) oder durch einen Hotkey.

15. Dezember 2006

Gleich und UnGleich

Manchmal muss man zwei Variablen auf Gleichheit prüfen.

Wenn man einfach nur "IF A = B THEN" schreibt, dann ist das keine Lösung. Falls eine der Variablen NULL ist, dann wird das Ergebnis des Ausdrucks ebenfalls NULL und das IF-Statement interpretiert dies als FALSE. Man benötigt also eine andere Vorgehensweise:

FUNCTION Equal (P_String1 IN VARCHAR2,
P_String2 IN VARCHAR2) RETURN BOOLEAN IS
BEGIN
IF P_String1 = P_String2
OR (P_String1 IS NULL AND P_String2 IS NULL) THEN
RETURN (TRUE);
ELSE
RETURN (FALSE);
END IF;
END;

FUNCTION UnEqual (P_String1 IN VARCHAR2,
P_String2 IN VARCHAR2) RETURN BOOLEAN IS
BEGIN
IF P_String1 != P_String2
OR ( P_String1 IS NULL
AND P_String2 IS NOT NULL)
OR ( P_String1 IS NOT NULL
AND P_String2 IS NULL) THEN
RETURN (TRUE);
ELSE
RETURN (FALSE);
END IF;
END;

Nun kann man Equal und UnEqual sehr einfach benutzen:

IF UnEqual (Var1, Var2) THEN
-- do something
ELSE
-- do something different
END IF;


versuch's

5. Dezember 2006

ON-ERROR und ON-MESSAGE-Trigger

Viele Entwickler haben das Problem mit Meldungen, die in der Maske angezeigt werden, zum Beispiel "FRM-40401: No changes to save".

Sie suchen dann nach Workarounds und manipulieren dann oft den :system.message_level:

KEY-COMMIT - Trigger auf Form-Ebene (Quick + Dirty)
BEGIN
:System.Message_Level := 25;
COMMIT;
:System.Message_Level := 5;
END;

oder speichern ihn zwischen:

DECLARE
V_Message_Level NUMBER;
BEGIN
V_Message_Level := :System.Message_Level;
:System.Message_Level := 25;
COMMIT;
:System.Message_Level := V_Message_Level;
END;


Das sind keine Best Practices. Diesen Code müsste man in hunderten Prozeduren unterbringen.

Fehler und Meldungen filtern ist die Lösung für ein gutes Message-Handling. Diese Prozedur zeigt die Technik:

ON-ERROR - Trigger auf Form-Ebene
DECLARE
V_Error_Code       NUMBER;
V_Error_Text       VARCHAR2 (2000);
V_DBMS_Error_Code  NUMBER;
V_DBMS_Error_Text  VARCHAR2 (2000);
BEGIN
V_Error_Code      := Error_Code;
V_Error_Text      := Error_Text;
V_DBMS_Error_Code := DBMS_Error_Code;
V_DBMS_Error_Text := DBMS_Error_Text;

IF V_Error_Code IN (40401, 40405) THEN
/*
|| 40401, 40405 - no changes to save / apply  get filtered
*/
NULL;
ELSIF V_Error_Code IN (-1034, -3114) THEN
/*
|| -1034, -3114 - not connected to database
*/
Message ('Not connect to database, exiting Form');
Exit_Form (no_validate);
ELSIF V_Error_Code IN (40508, 40735)
AND   V_DBMS_Error_Code BETWEEN -20999 AND -20000 THEN
/*
|| -20000 errors are raised by RAISE_APPLICATION_ERROR 
|| They are handled in a different way
*/
Show_and_Log_DB_Error (V_DBMS_Error_Text);
ELSE
/*
|| All other errors went into Show_and_Log_Error, where they
|| get inspected, analyzed and logged.
*/
Show_and_Log_Error (V_Error_Code);
END IF;
END;

6. November 2006

OOW Zusammenfassung

Dieses Bild zeigt die Howard-Street, während der OOW. Die gesamte Strasse wurde in ein riesiges Zelt verwandelt:



























Regis Louis und seine Überblick auf JDeveloper 11g war sehr erfrischend, da das Toolset das Zentrum der neuen Fusion-Technologie wird.




















Steven Feuerstein zeigte in seinem Vortrag neue Wege für ein Exception-Handling in PL/SQL und wie man es professionell mit Unit-Testing-Software verbinden kann (wie z.B. utPLSQL).




















Sehr interessant war seine Ankündigung, dass er eine neue Software namens Quest Code Tester herausbringen wird, dass den Entwickler beim Erstellen von Test-Fällen für automatisierte PL/SQL-Unittests unterstützt. Erscheinungsdatum in ca. 6 Monaten. Hier ist der Link zu seiner neuen Homepage für all diese Tools:




http://www.toadworld.com/




Bryn Llewellyn (Mit-Erfinder des PL/SQL) zeigte uns in seiner "Meet the Guru"-Stunde die neuen Features von der Oracle Databank 11g.

Am spannendsten ist die neue "edition". D.h. man kann eine neue Version eines Packages / View / Tabelle erzeugen. Mit einem einfachen "alter system set edition = ..." kann man dann zwischen den Versionen wechseln.

Z.B. wenn man eine Reihe von neuen Packages hat und diese auf der Produktions-DB testen will. Diese Packages werden dann in einer Edition erstellt. Danach kann man dann mit obigem Befehl die beiden Versionen wechseln. Das Testen der neuen Package und das Zurücksetzen auf den alten Stand geht in Sekunden!














Das waren die interessantesten Neuerungen auf der Oracle Open World 2006

26. Oktober 2006

Oracle Open World 2006

Gross, grösser, Moscone! Das ist es, was mir in Erinnerung bleibt, wenn ich an die diesjährige Oracle Open World denke.

42000 Besucher waren auf Larry's Konferenz und es wird von Jahr zu Jahr mehr


Larry's Ankündigung in diesem Jahr war: "Wir geben Dir Red Hat Linux-Support, besser als jeder andere im Markt und kostengünstiger".


Seine aktuelle Jacht:

22. Oktober 2006

Ankunft in San Francisco

Gestern startete ich meinen diesjährigen Oracle Open World Trip.

Hier sind einige Impressionen der ersten Nacht. Um 7 Uhr in der Frühe startete der Nike's Woman Marathon in San Francisco am Union Square, direkt vor unserem Hotel.

Die besten Läufer durften schon um 6:40 Uhr starten.









































19. Oktober 2006

AOUG Konferenz 2006

Gestern war ich bei der jährlichen österreichischen Oracle User Group in Wien eingeladen.

Kennen sie Wien? Die Stadt ist so liebenswert mit all ihren Burgen und Schlössern, alten Gebäuden und Kaffee-Häusern. Sie würden es lieben.

Mein Vortrag lautete "Oracle Forms 10g und die Kommunikation mit SOA durch BPEL"

29. September 2006

Die OOW kommt näher und näher

Oh man! Es ist verdammt harte Arbeit um die OOW-Schedule zu füllen und so viele verschiedene Möglichkeiten boten sich mir noch nie.

Hunderte von guten Vorträgen und alle werden an 4 Tagen parallel gehalten. Man sitzt also vor seinem Browser und kreuzt die wichtigsten Vorträge an. Aber welche Vorträge sind die wichtigsten, wenn man durch 60 parallele Slots pro Stunde durchscrollt? Alle Titel und Autoren durchzugehen ist schon ein Stück Arbeit.

und dann: Tom Kyte's Vortrag ist voll - oh no! - diejenigen, die zu spät kamen mussten auf eine Warteliste
aber: Steven's Vortrag ist noch nicht ganz voll! Schnell den letzten Platz buchen, bevor auch der weg ist

3. August 2006

Neuer Vortrag

Letzte Woche war heftig!

Letzten Montags bekam ich die Einladung zur Oracle World von der EOUC.

Freitags lehnte Oracle meinen Vortrag ab (Forms-Integration in BPEL) da sie den gleichen Vortrag aus Oracle-Sicht halten wollten. Sie gaben mir aber eine zweite Chance für ein anderes Thema.

Diesen Mittwoch bekam ich eine Einladung für meinen Vortrag über BI Beans.

Developing Powerful Oracle Business Intelligence Beans in Oracle Forms

BI Beans ersetzt Oracle Graphics als neues graphisches Tool in Forms. Für diese neue Java-basierte Technologie braucht der Forms Entwickler keine Java-Kenntnisse. Im Vortrag lernt man, wie BI Beans richtig installiert werden, wie die Kommunikation zwischen Forms und BI Beans aufgebaut wird und wie man tolle graphische Anwendungen damit aufbaut.

25. Juli 2006

Einladung zur OOW 2006

Juhu ! Ich wurde zur Oracle Open World 2006 nach San Francisco eingeladen.

Oracle Forms & BPEL do work hand in hand in the SOA-world

Abstract:

With the come up of service-oriented-architectures it is mandatory that Oracle Forms communicates with the companies automated business processes. In this presentation you'll see, how easy it is to establish a "dialogue" between Oracle Forms and BPEL. The integration will be demonstrated with an example-application: the setup in Oracle Forms, the web-services you need in and around the BPEL-engine and how you poll process-messages in Oracle Forms.

24. Juli 2006

Erstellen eines Forms Frameworks

Seit mehr als 10 Jahren arbeite ich nun schon mit Oracle Forms und denke über die Frage nach: Wie kann man am effizientesten mit dieser 4GL Sprache umgehen?

Es ist sehr einfach um eine Formsmaske zu erstellen und laufen zu lassen. Eine grosse Anwendung mit vielen hundert Formsmasken auf diese Weise zu entwickeln ist jedoch unsinnig, da man das Rad täglich neu erfinden müsste.

Ich wollte das Rad also nur einmal erfinden um es dann in allen Formsmasken benutzen zu können. Der beste Weg hierzu ist:

- Erstelle einen Style Guide für die gesamte Applikation
- Definiere eine Referenz-Form und Templates für die Entwickler
- Erzeuge Prototypen mit dem Framework

Das hört sich so einfach an und es ist auch so einfach, wenn man genügend Erfahrung hat und weiss, wie Forms arbeitet.

Hier ist der Link zu meinem Sourceforge-Projekt, wo ich die Sourcecodes publiziere, Richtlinien für das Framework beschreibe und vieles mehr...

http://sourceforge.net/projects/forms-framework/


Einige Punkte des Style Guides sind
- Exception Handling
- Dynamisches Meldungswesen
- Zugriffsrechte für Forms und Spezial-Funktionen
- Dynamische Menüs für die Start-Applikation
- PL/SQL-Libraries

21. Juli 2006

CLOB's in Forms 6i

Der neue Datentyp CLOB wird in Oracle Forms 6i noch nicht unterstützt.

Erfinden wir doch einfach einen Workaround !

Voraussetzung: Tabelle EMP ist in der DB und hat eine Spalte Note_CLOB, es gibt eine Maske mit dem Block EMP und allen Spalten ausser dem CLOB.

Anforderung: Der CLOB soll aus der DB gelesen und angezeigt werden. Desweiteren soll er editierbar sein

Zuerst erstellen wir ein Textitem "Note_CLOB" im Block EMP:

Item-Properties:
- Data Type CHAR
- Maximum Length 32000
- Database-Item No

Item-Trigger:
- WHEN-VALIDATE-ITEM
:EMP.EMPNO := :EMP.EMPNO;

Block-Trigger:
- POST-QUERY
POQ_EMP;

- PRE-UPDATE
PRU_EMP;

Diese Prozeduren werden in der Maske benötigt

PROCEDURE POQ_EMP IS
V_String VARCHAR2 (1000);
V_Index NUMBER := 0;
BEGIN
LOOP
V_String := Read_CLOB (:EMP.EMPNO, V_Index);
IF V_String IS NOT NULL THEN
:EMP.Note_CLOB := :EMP.Note_CLOB || V_String;
V_Index := V_Index + 1;
ELSE
EXIT;
END IF;
END LOOP;
END;

PROCEDURE PRU_EMP IS
V_String VARCHAR2 (1000);
V_Index NUMBER := 0
BEGIN
Clear_CLOB (:EMP.EMPNO);
LOOP
V_String := Substr (:EMP.Note_CLOB, 1 + V_Index * 1000, 1000);
IF V_String IS NOT NULL THEN
Append_CLOB (:EMP.EMPNO, V_String);
V_Index := V_Index + 1;
ELSE
EXIT;
END IF;
END LOOP;
END;


Diese Prozedur liegt in der Datenbank


PROCEDURE CLEAR_CLOB (P_EMPNO IN EMP.EMPNO%TYPE) IS
BEGIN
UPDATE EMP SET Note_CLOB = NULL
WHERE EMPNO = P_EMPNO;
END;

PROCEDURE APPEND_CLOB (P_EMPNO IN EMP.EMPNO%TYPE, P_STRING IN VARCHAR2) IS
BEGIN
UPDATE EMP SET Note_CLOB = Note_CLOB || P_String
WHERE EMPNO = P_EMPNO;
END;

FUNCTION READ_CLOB (P_EMPNO IN EMP.EMPNO%TYPE, P_INDEX IN NUMBER) RETURN VARCHAR2 IS
V_STRING VARCHAR2 (2000);
BEGIN
SELECT SUBSTR (Note_CLOB, 1 + P_Index * 1000, 1000)
INTO V_String
FROM EMP
WHERE EMPNO = P_EMPNO;
RETURN (V_String);
END;

mit dieser Technik kann man aus einem CLOB die ersten 32 KB auslesen und verändern. Bei grösseren CLOB geht dies nicht.

versuche und teste es !