PDA

View Full Version : Frage zu CLI Apis



Seiten : [1] 2

sim
13-02-04, 07:33
Hallo,

vielleicht kann mir ja jemand helfen.

Ich bin gerade dabei eines von unseren Programmen zu überarbeiten. Mit diesem Programm können jegliche SQLs
ohne großen Programmieraufwand in ILE RPG Programmen
verwendet werden.

Dazu muß lediglich ein Serviceprogramm eingebunden (sagen wir mal p_sql) und dann ne Prozedur mit dem jeweiligen SQL aufgerufen werden. (bsp: dow sql_befehl (SQLStatement); .......)
Die Ergebnismenge wird dann per Export / Import Datenstruktur übergeben und steht dann zur Verfügung.


Nun zum Problem:
Die neue Version dieses Programms soll nun die CLI Apis zur direkten Steuerung des SQLs verwenden.
Die einzelnen Felder der Ergebnismenge habe ich mit dem API SQLBindCol mit einer Programmvariablen verbunden. Jedoch muß dies für jedes Feld gemacht werden und ist im nachhineine noch recht aufwendig. (konvertierung der versch. feldarten, usw...)


Gibt es ne Möglichkeit den kompletten Ergebnisstring auf einmal zurückzuliefern ? (z.Bsp: in ein 32000a großes Feld)


Ich hoffe das war einigermaßen verständlich.

Fuerchau
13-02-04, 07:59
Nein !

SQLBindCol ist der einzige Weg !

sim
13-02-04, 08:08
Hmm, schade.

Dann aber gleich noch ne Frage:

Wie verwende ich SQLBindCol wenn ich gepackte Felder habe ?

Im Moment hab ich es so gemacht, daß ich alle Felder als CHAR zurückliefere. Natürlich müsste ich im Anschluß noch ins richtige Format konvertieren. Kann ich das direkt mit SQLBindCol bewerkstelligen ?

Fuerchau
13-02-04, 09:00
Schau hierzu mal ins Handbuch zum Thema SQL-Feldtypen.

In der Source QSYSINC/H Member SQLCLI findest du alle Deklarationen und Aufrufe.

Mit SQLColAttributes bekommst du die Info über Typ und Ausprägung. Dies Werte kannst du direkt an SQLBindCol weitergeben.

Für die korrekte Berechnung des Gesamtpuffers bist du selbst verantwortlich.

Für die Beschreibung aller Funktionen siehe
http://publib.boulder.ibm.com/iseries/v5r2/ic2924/info/cli/rzadpmst02.htm#ToC

Anmerkung:

Wenn du als Typ immer CHAR verwendest, findet bei Dezimalfeldern eine numerische linksbündige Aufbereitung statt, und zwar genauso wie wenn du entsprechend castest:

"select char(num1), char(num2) ...."

Das Dezimalzeichen wird mt SQLSetStmtAttr festgelegt (Default Dezimalpunkt!).

sim
13-02-04, 10:20
Den Link kannte ich schon. Danke.

Anstelle von SQLColAttributes hab ich SQLDescribeCol verwendet gefolgt von SQLBindCol mit dem entsprechenden Feldtyp.


Bei einem gepackten Feld (z.Bsp: 7p 0) liefert der Describe als Feldtyp 3 zurück = SQL_DECIMAL

In der Variable die bei BindCol angegebn wurde steht dann auch Müll drin.

In der Hilfe konnte ich auch nichts genaueres finden.

Kann mir da jemand mal ein Beispiel zeigen ?

Fuerchau
13-02-04, 11:30
Schau dir den Inhalt (per Debugger) Hex an !

ein gepackter Wert benötigt ((Länge / 2) * 2 + 1) Stellen.
Das Format ist dann x'1234567F' => 7 Tetraden + Vorzeichen.

SQLCLI liefert keinen Schrott !

Statt SQL_DECIMAL kannst du SQL_NUMERIC verwenden. Dann erhältst du ein gezontes Feld (7S 0).

Fuerchau
13-02-04, 11:51
Wofür benötigst du das denn überhaupt ?
Eine solche Schnittstelle ist ja reichlich kompliziert.
Auch die Übergabe als Datenstruktur ist ja nicht so einfach.
Was machst du wenn mehr als 16MB an Daten anfallen ?

Mein Tool SQLCPY bietet da eine Programmschnittstelle.

sim
13-02-04, 11:59
Wie gesagt besteht dieses Tools bereits, jedoch ist dies
nicht per CLI gelöst sondern per SQLDA.
Siehe Beispiel unten.

Das Problem ist hierbei das ich immer den gleichen Cursor verwende. Somit kann ich nicht mehrere SQL Befehle in
einer Schleife über dieses Tool laufen lassen.


Darum wollte ich es nun per CLI Versuchen da man hier
über den Handle so eine Steuerung hinbekommt.


c/exec sql include sqlda
c/end-exec
c/exec sql prepare s0 from :statement
c/end-exec

c eval sqln = 50
c/exec sql describe s0 into :sqlda
c/end-exec
.....

c/exec sql describe s0 into :sqlda
c/end-exec
....
c/exec sql declare c0 cursor for s0
c/end-exec
......
c/exec sql open c0
c/end-exec

...

c/exec sql
c+ fetch c0 for 1 rows
c+ using descriptor :sqlda
c+ into :satz_ds:ind
c/end-exec

mfg, sim

Fuerchau
13-02-04, 12:48
Das geht auch dynamisch mit SQL !

Im Descriptor kannst du auch eine Adresse für das Datenfeld angeben (entspricht dem SQLBindCol).

Beim Fetch läßt du das INTO weg !

Die Nullflags erhältst du auch im Descriptor.

Der Describe Cursor ist nur zur Compilezeit wichtig.

Ein erneuter Prepare ist jederzeit möglich !

sim
27-02-04, 12:11
ok,

aber kann ich dann 2 verschachtelte SQLs in einer Schleife laufen lassen ?

quasi:
--------
// SQL 1
dow sql_befehl('SELECT * FROM KUNDEN');
kunden_ds = SQLErgebnis_ds;
......
// SQL 2
dow sql_befehl('SELECT * FROM RECHNUNG');
rechnung_ds = SQLErgebnis;
enddo;
.......

enddo;


Da ich in der Prozedur sql_befehl ja immer den declare mit c0
mache kann ich eine verschachtelte Abfrage, wie im Beispiel oben, NICHT anwenden.

Sobald ich die SQL2 Anweisung ausführe wird der SQL1 Cursor geschlossen, -->

Wie kann ich die Cursor selber Verwakten bzw vom einem SQL zum anderen wechseln (beide Cursor bleiben geöffnet).


Wars so verständlicher ?