[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Jan 2012
    Beiträge
    1.120

    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

  2. #2
    Registriert seit
    Jan 2012
    Beiträge
    1.120
    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.

  3. #3
    Registriert seit
    Aug 2001
    Beiträge
    2.874
    • 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
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  4. #4
    Registriert seit
    Nov 2020
    Beiträge
    331
    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.

  5. #5
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    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.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  6. #6
    Registriert seit
    Jan 2012
    Beiträge
    1.120
    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

  7. #7
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    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.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  8. #8
    Registriert seit
    Aug 2001
    Beiträge
    2.874
    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)
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  9. #9
    Registriert seit
    Jan 2012
    Beiträge
    1.120
    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

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    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
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

Similar Threads

  1. Variable innerhalb von EXEC SQL nutzen
    By _MG_ in forum NEWSboard Programmierung
    Antworten: 11
    Letzter Beitrag: 15-01-17, 16:05
  2. Serviceprogramm und SQL-Command „get diagnostics“
    By opeker in forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 21-10-15, 12:42
  3. User Defined Function in SQL, Datumsübergabe an Serviceprogramm
    By dschroeder in forum NEWSboard Programmierung
    Antworten: 27
    Letzter Beitrag: 02-12-14, 09:33
  4. SQL Funktion ruft Serviceprogramm auf - Parameter übergabe
    By loisl in forum NEWSboard Programmierung
    Antworten: 4
    Letzter Beitrag: 08-11-13, 16:37
  5. RCLSTG - soll ich oder soll ich nicht?
    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
  •