-
SQL USF soll RPGLE-Serviceprogramm nutzen: Parameterproblem
Hallo,
ich verzweifle langsam an einem Parameterproblem. Ich habe ein RPG-Serviceprogramm, dass ich als SQL-UDF zur Verfügung stellen möchte. Das RPG-Programm läuft im RPG-Umfeld einwandfrei. Nur die UDF bekomme ich nicht zum Laufen:
Die UDF übergibt nur die ersten 3 Parameter. Ich habe das debugged. Die Parameter kommen korrekt im RPG an und das Rückgabe-Clob sieht zum Zeitpunkt des Return auch vollkommen korrekt aus.
RPG:
Code:
dcl-proc DAXWS_createErrorJSON export;
dcl-pi *n varucs2(60000);
i#_routine varchar(100) const;
i#_errCode varchar(40) const;
i#_errMsg varucs2(300) const options(*nopass);
i#_errField varchar(100) const options(*nopass);
i#_msgType char(1) const options(*nopass);
i#_errorMsgDS likeds(COPY__###_errorMsgDS_templ) const options(*nopass);
i#_zusatz varchar(20) const options(*nopass);
end-pi;
dcl-s clobDS2 sqltype(dbclob:60000) ccsid(1200); //dbclob = Double Byte Clob
...
return %trim(%subst(clobDS2_data:1:clobDS2_len));
Hier die komplette UDF:
(Man beachte die Double Byte Codierung nvarchar!)
Code:
create or replace function edpgmlib/DAXWS_createErrorJSON (
i#_routine varchar(100),
i#_errCode varchar(40),
i#_errMsg nvarchar(300) default '' )
returns nvarchar(10000)
specific edpgmlib/DAXWS_createErrorJSON
language rpgle
not deterministic
modifies sql data
called on null input
disallow parallel
external name 'EDPGMLIB/DAXWS908A(DAXWS_CREATEERRORJSON)'
parameter style general;
Wenn ich die SQL-Funktion aufrufe, bekomme ich:
12:29:28 FAILED [VALUES - 0 rows, 11.937 secs] 1) [Code: -443, SQL State: 38501] [SQL0443] *N Ursache . . . . : Von einem Auslöserprogramm, einer externen Prozedur oder einer externen Funktion wurde ein Fehler erkannt und an SQL zurückgegeben. Ist der Fehler in einem Auslöserprogramm aufgetreten, ...
Die Frage ist aus meiner Sicht: Wie bekomme ich den Rückgabewert varucs2(60000) auf ein passendes SQL-Feld gemappt? Ich habe es auch schon mit dbclob(60000) ccsid 1200 versucht. Hatte auch keinen Erfolg.
Dieter
-
Ich habe inzwischen den Verdacht, das es gar kein Mapping Problem ist. Ich glaube, unser zugekauftes Sicherheitstool verursacht einen internen Absturz.
Ich habe nämlich andere Programme / UDFs gefunden, die funktionieren. Da ist das Mapping mit dbcob(xxxx) 1200 gemacht.
-
- Ich würde für UCS2 immer Graph()/VarGraphic() CCSID 13488 verwenden - Für CCSID 1200 würde ich auch in RPG VARGRAPH mit CCSID verwenden.
- Alphanumerische Felder > 32740 Byte können von SQL nicht direkt verarbeitet werden. Solche Felder müssen als CLOB (single byte) oder DBCLOB (double byte) definiert werden (z.B. SQLTYPE(CLOB: 100000))
- Ein Large Object ist (untendrunter) ein Feld mit Variabler Länge allerdings mit führenden 4 Byte (10U 0) für die Länge.
- Wenn in der eigentlichen RPG-Funktion mehrere Optionale Parameter definiert sind, habe ich diese Funktionen mit (weiteren) RPG-Funktionen gewrappt, die jeweils eine fixe Anzahl an Parameter hatten. Innerhalb der Funktionen habe ich lediglich die Original-RPG-Prozedur aufgerufen.
Birgitta
-
Ich würde im SRVPGM noch eine weitere (Wrapper-)Prozedur machen, wo der Rückgabeparameter varucs2(10000) ist.
Diese Wrapper-Prozedur ruft dann deine Original-Prozedur auf und schneidet die Werte ab, wenn das für den Aufrufer wirklich ok ist.
Oder du wandelst in der Wrapper-Prozedur den Wert in einen anderen Datentyp um.
-
Vergleiche dies mal:
RPGLE: dcl-pi *n varucs2(60000);
SQL: returns nvarchar(10000)
Da die Längeninformation in 2 oder 4 Bytes vor der variablen stehen, darfst du dann nicht mehr als 10000 Zeichen zurückgeben.
Automatik: Bis 32K 2 Bytes, > 32K 4 Bytes.
Besser ist es natürlich, du passt die Definitionen an.
Zusätzlich gibt es noch die generelle Einschränkung dass ein Puffer 64K nicht überschreiten darf, ansonsten ist ein CLOB/BLOB zu verwenden-
nvarchar(60000) enspricht nun mal ebenso varchar(120000).
Es wäre also besser, hier auf CLOB umzusteigen.
Damit müsste auch deine Prozedur u.U. einen DBCLOB zurückgeben.
-
Vielen Dank für eure Antworten.
Die Ungleichheit zwischen varucs2(60000) und nvarchar(10000) ist mir bewusst. Ich kann nvarchar ja nicht auf 60000 bringen. Das ist für eine SQL-Variable zu groß.
Im vorliegenden Fall weiß ich, dass das Rückgabeergebnis maximal 1000 Zeichen lang sein wird, wenn ich das ganze per SQL aufrufe. Wenn ich also mit der Ungleichheit 60000 vs 10000 leben könnte, müsste es denn dann eigentlich gehen? Ist die Übergabe zwischen Feldern mit 4 führenden Längenbytes und 2 führenden Längenbytes grundsätzlich möglich? Oder muss da immer manuell gecastet werden?
Ich haben bei uns inzwischen ein Programm und eine UDF gefunden, bei denen das ganze funktioniert. Dort wird vom RPG varucs2(100000) zurückgegeben und in der UDF wird das als dbclob(100000) ccsid 1200 empfangen.
Nochmal zu den Aussagen von Birgitta:
Ich verstehe da leider die Unterschiede in den CCSIDs nicht:
Die größten Teile unserer Anwendung nutzen char und varchar. Vor einigen Jahren sind wir dann dazu übergegangen, Unicode zu verwenden. Da haben wir vieles auf UCS2 umgestellt. In den DDS-beschriebenen Tabellen haben wir den Datentyp G mit CCSID 1200 eingeführt. In den SQL beschriebenen Tabellen haben wir nvarchar eingeführt. Im RPG nutzen wir für Unicode UCS2.
Ich dachte mal irgendwo gelesen zu haben, dass diese Datentypen gleich sind, nur andere Schreibweise. Grundsätzlich klappt das auch. Ich würde nur ungern Experimente machen und jetzt Teile auf Graphic 13488 umstellen. Oder ist das zwingend notwendig?
Ich werden jetzt nochmal etwas weiter testen und versuchen, ein 2. RPG-Programm mit anderen Datentypen als workaround dazwischen zu setzen.
LG, Dieter
-
UCS2 und NVARCHAR sind im Prinzip identischen.
Allerdings muss man ILERPG in den CTLOPT beibringen dass UCS2 entweder 13488 (alte UCS2) oder 1200 (neue UCS2, eigentlich UTF-16, also variabel UCS2 oder UCS4).
In SQL ist N[var]char als CCSID 1200 definiert.
VARLEN.
In DDS und ILERPG kann man die Längeninformation 2/4 festlegen.
z.B. varchar(1000:2) oder varchar(1000:4);
Nur bei SQL ist das halt automatisch.
Bis 32K eben 2, > 32K dann 4.
Wenn dann also 4 Bytes übergeben werden und nur 2 Bytes reinkommen, ist die Länge eben 0.
Umgedreht, wenn 4 Bytes erwartet werden und 2 Bytes ankommen ist die Länge > 64K, was zu Speicherproblemen führt.
Das ist eben das ganze Problem mit SQL und ILERPG, dass da nichts typesafe ist.
Wenn du mit Varying-Feldern arbeiten willst, musst du die Definitionen auf jeden Fall identisch halten.
Alles andere bringt, wie D*B gerne sagt, nur Murks und Wackelhaufen.
Wenn du aber mit JSON und Prozeduren/Funktionen umgehen willst, solltest du die auf DBCLOB in allen Belangen festlegen.
DBCLOB kann man im RPGLE allerdings auch Redefinieren (Pointer) mit varucs(nnnn:4) um native eben mit dem DBCLOB umgehen zu können.
-
Code:
RPG varucs2(100000) zurückgegeben und in der UDF wird das als dbclob(100000) ccsid 1200
Felder mit Variabler Länge, und > 65535 Bytes haben in RPG automatisch 4 führende Bytes.
Felder mit variabler Länge und < 65535 Bytes haben in RPG per default 2 führende Bytes.
Man kann jedoch in RPG auch kürzere Felder mit 4 führenden Bytes definieren.
UCS2 entspricht der CCSID 13488 (und nicht 1200 - UTF-16).
lt. Google:
"Der wesentliche Unterschied zu UTF-16 ist, dass UCS-2 die Zeichen des Surrogat-Bereichs nicht unterstützt. "
IBM i Documentation:
UCS-2 and its relationship to Unicode (UTF-16)
-
Vielen Dank nochmal an euch beide.
Ich habe inzwischen weitergetestet und habe die beschriebenen Punkte mit den Längenbytes genau so verifiziert, wie ihr das beschrieben habt.
Durch einen RPG-Adapter klappt jetzt auch der Aufruf mittels SQL-UDF.
Bei den Zeichensätzen hoffe ich, dass wir bei uns keine Änderungen machen müssen.
LG, Dieter
-
Ich bezog mich u.a. auch auf die CTLOPT-Spezifikation für RPGLE.
Die Funktionen %char() und %ucs2() beziehen nämlich von daher die Art der
Codewandlung:
CCSID(*UCS2:1200)
Und 1200 ist UTF16, da man statt 1200 auch *UTF16 verwenden kann.
Es gibt für RRPGLE jedoch nur %UCS2 und den "C" Feldtyp.
Eine Eval zwischen C und A ruft intern automatisch %char() oder %ucs2() auf.
https://www.ibm.com/docs/en/i/7.5?to...ontrol-keyword
Similar Threads
-
By _MG_ in forum NEWSboard Programmierung
Antworten: 11
Letzter Beitrag: 15-01-17, 16:05
-
By opeker in forum NEWSboard Programmierung
Antworten: 2
Letzter Beitrag: 21-10-15, 12:42
-
By dschroeder in forum NEWSboard Programmierung
Antworten: 27
Letzter Beitrag: 02-12-14, 09:33
-
By loisl in forum NEWSboard Programmierung
Antworten: 4
Letzter Beitrag: 08-11-13, 16:37
-
By Mädele in forum IBM i Hauptforum
Antworten: 8
Letzter Beitrag: 23-04-03, 07:41
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- You may not post attachments
- You may not edit your posts
-
Foren-Regeln
|
Erweiterte Foren Suche
Google Foren Suche
Forum & Artikel Update eMail
AS/400 / IBM i
Server Expert Gruppen
Unternehmens IT
|
Kategorien online Artikel
- Big Data, Analytics, BI, MIS
- Cloud, Social Media, Devices
- DMS, Archivierung, Druck
- ERP + Add-ons, Business Software
- Hochverfügbarkeit
- Human Resources, Personal
- IBM Announcements
- IT-Karikaturen
- Leitartikel
- Load`n`go
- Messen, Veranstaltungen
- NEWSolutions Dossiers
- Programmierung
- Security
- Software Development + Change Mgmt.
- Solutions & Provider
- Speicher – Storage
- Strategische Berichte
- Systemmanagement
- Tools, Hot-Tips
Auf dem Laufenden bleiben
|
Bookmarks