7. CLI und ODBC Datenbankprogrammierung CLI/ODBC CLI/ODBC § Beide Standards basieren auf der X/Open Call-Level Interface Spezifikation § CLI (call level interface) - Prozeduren/Funktionen zur Kommunikation mit dem DBMS - Definition und Ausführung von Anfragen - Verarbeitung von Ergebnissen § ODBC (Open Data Base Connectivity) - CLI-konforme Implementierung für Microsoft Windows - Erweitert X/Open CLI um zusätzliche Funktionalität - Zugriff auf verschiedene Datenbanksysteme über systemspezifische Treiber möglich - Dynamisches Laden von Treibern (implementiert als DLL) 2 Architektur im Weiteren nur DB2 CLI 3 Unterstützte DB2-Features UNTERSTÜTZTE DB2-FEATURES § § § § § Compound SQL UDTs UDFs und Stored Procedures Distributed Unit of Work (DUOW) 2-Phasen-Commit-Protokoll CLI-FUNKTIONSÜBERSICHT § http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000553.html CLI-INCLUDE-DATEIEN § Unter \sqllib\include\sqlcli.h und sqlcli1.h § Enthalten CLI-Konstanten und Funktionsprototypen 4 CLI Funktionsaufrufe Aufrufsequenz § Initialisierung - Allokation von Systemressourcen Referenzierung über Handle § Anfragebearbeitung § Ressourcenfreigabe - Freigabe aller allokierter Ressourcen HANDLE § § § § Verweis auf globale Datenstruktur zur Kommunikation mit DBMS C-Datentyp: SQLHANDLE Erfordert explizite Allokation 5 Handle-Arten HANDLE-ARTEN § § § § Environment-Handle: verwaltet Informationen über globalen Zustand einer Anwendung (Attribute, Verbindungen) Connection-Handle: Verwalten von Verbindungsdaten einer Verbindung Statement-Handle: Information zu einer SQL-Anweisung Binden von SQL-Platzhalter Kompilieren und Ausführen einer Anweisung Metadaten zu Ergebnismengen Binden von Spalten der Ergebnismenge Abrufen von Daten aus der Ergebnismenge Descriptor-Handle: Daten zu Ergebnisspalten bzw. Parametern 6 Initialisierung INITIALISIERUNG HTTP://PUBLIB.BOULDER.IBM .COM /INFOCENTER/DB2 LUW /V9 R7/TOPIC/COM .IBM .DB2.LUW.APDV.CLI.DOC/DOC/R0000556.HTML § SQLAllocHandle (SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle); § Vor ODBC 3.0: SQLAllocConnect(), SQLAllocEnv() und SQLAllocStmt() § InputHandle bildet Kontext für neu anzulegenden OutputHandle InputHandle (Kontext) OutputHandle (zu erstellen) Umgebungs-Handle SQL_NULL_HANDLE SQL_HANDLE_ENV Verbindungs-Handle SQL_HANDLE_ENV SQL_HANDLE_DBC Anweisungs-Handle SQL_HANDLE_DBC SQL_HANDLE_STMT Descriptor-Handle SQL_HANDLE_DBC SQL_HANDLE_DESC 7 Verbindungsaufbau VERBINDUNGSAUFBAU HTTP://PUBLIB.BOULDER.IBM.COM/INFOCENTER/DB2LUW/V9R7/TOPIC/COM.IBM.DB2.LUW.APDV.CLI.DOC/DOC/R0000575.HTML § SQLConnect ( SQLHDBC SQLCHAR SQLSMALLINT SQLCHAR SQLSMALLINT SQLCHAR SQLSMALLINT ConnectionHandle, *ServerName, ServerNameLength, *UserName, UserNameLength, *Authentication, AuthenticationLength) § Stellt Verbindung zur Datenbank her § Längenargument für Zeichenketten - exakt - Null-terminierter String (SQL_NTS) - NULL-Werte (SQL_NULL_DATA) 8 Initialisierung BEISPIEL (MYCLIAPP.C) SQLHANDLE HENV , HDBC , HSTMT ; SQLALLOCHANDLE(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &HENV); IF (HENV != 0) SQLALLOCHANDLE(SQL_HANDLE_DBC, HENV , &HDBC); (HDBC != 0) cliRC = SQLConnect(hdbc, (SQLCHAR *) "SAMPLE", SQL_NTS, (SQLCHAR *) "db2ins**", SQL_NTS, (SQLCHAR *) "*****", SQL_NTS); IF (CLIRC == SQL_SUCCESS) SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); IF 9 Terminierung TERMINIERUNG § SQLDisconnect(SQLHDBC ConnectionHandle) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000583.html - Verbindungslösung von der Datenquelle - Treiber freigeben § SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000598.html - Verbindungsspeicher zur Datenquelle freigeben - Verwendet für SQL_HANDLE_STMT, SQL_HANDLE_DBC, SQL_HANDLE_DESC und SQL_HANDLE_ENV BEISPIEL SQLFreeHandle(SQL_HANDLE_STMT, hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_ENV, henv); 10 Anfrageverarbeitung ANFRAGEVERARBEITUNG § SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt) - § Allokiert Speicher für eine SQL-Anweisung Kompilieren und Ausführen 1. SQLPrepare( SQLHSTMT hstmt, SQLCHAR *StatementText, SQLINTEGER TextLength) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000635.html 2. Anweisung/SP-Aufruf am DB-Server kompilieren SP-Syntax: "{CALL <name>(?,…)}" SQLBindParameter( SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType, SQLSMALLINT ValueType, SQLSMALLINT ParameterType, SQLUINTEGER ColumnSize, SQLSMALLINT DecimalDigits, SQLPOINTER ParameterValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StrLen_or_IndPtr ) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0002218.html - wenn die Anweisung Parametermarker enthält 11 Anfrageverarbeitung (2) ANFRAGEVERARBEITUNG § Kompilieren und Ausführen 3. SQLExecute(SQLHSTMT hstmt) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000589.html - § Ausführung der kompilierten Anweisung Referenz und optionale Parameter als Eingabe übergeben Direkte Ausführung 1. SQLExecDirect(SQLHSTMT hstmt, SQLCHAR *StatementText, SQLINTEGER TextLength) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000588.html - Ausführen der SQL-Anweisung 12 Anfrageverarbeitung (3) VERARBEITUNG DER ERGEBNISMENGE § § Nur bei SELECT- und VALUE-Anweisungen Ermitteln der Struktur der Ergebnismenge - SQLNumResultCols(SQLHSTMT SQLSMALLINT hstmt, *ColumnCountPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000632.html - Ermittelt Anzahl der Ergebnisspalten SQLDescribeCol(SQLHSTMT hstmt, SQLSMALLINT ColumnNumber, SQLCHAR *ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT *NameLengthPtr, SQLSMALLINT *DataTypePtr, SQLUINTEGER *ColumnSizePtr, SQLSMALLINT *DecimalDigitsPtr, SQLSMALLINT *NullablePtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000580.html - Ermittelt allgemeine Spalteninformationen (Name, Typ, Genauigkeit, …) 13 Anfrageverarbeitung (4) VERARBEITUNG DER ERGEBNISMENGE § Ermitteln der Struktur der Ergebnismenge - SQLColAttribute(SQLHSTMT SQLSMALLINT SQLSMALLINT SQLPOINTER SQLSMALLINT SQLSMALLINT SQLPOINTER hstmt, ColumnNumber, FieldIdentifier, CharacterAttributePtr, BufferLength, *StringLengthPtr, NumericAttributePtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000569.html - Ermittelt speziellere Spalteninformationen (Kardinalität, Nullwerte vorhanden?, UDDT-Name) 14 Anfrageverarbeitung (5) VERARBEITUNG DER ERGEBNISMENGE § Ausgabe der Ergebnismenge - SQLBindCol(SQLHSTMT hstmt, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StrLen_or_IndPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com .ibm.db2.luw.apdv.cli.doc/doc/r0000558.html Binden von Anwendungsvariablen an Spalten der Ergebnismenge (optional) - SQLFetch(SQLHSTMT hstmt) − - SQLGetData(SQLHSTMT hstmt, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StrLen_or_IndPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com .ibm.db2.luw.apdv.cli.doc/doc/r0000604.html − − Alternativ zu SQLBindCol() für ungebundene Spalten Aufruf nach SQLFetch() http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com .ibm.db2.luw.apdv.cli.doc/doc/r0000591.html − Zeilenweises Einlesen der Daten in die gebundenen Variablen 15 Anfrageverarbeitung (6) 16 Anfrageverarbeitung (7) BEISPIEL SQLHANDLE HSTMT = 0; SQLCHAR SQLSTMT[255]; SQLCHAR JOBTYPE[10]; SQLCHAR LASTNAME[25]; … STRCPY(SQLSTMT, "SELECT LASTNAME FROM EMPLOYEE WHERE JOB = ?"); STRCPY(JOBTYPE, "DESIGNER"); SQLPREPARE(HSTMT, SQLSTMT, SQL_NTS); SQLBINDPARAMETER(HSTMT, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(JobType), 0, JobType, sizeof(JobType), NULL); SQLEXECUTE(HSTMT); 17 Anfrageverarbeitung (8) …BEISPIEL FORTSETZUNG SQLBindCol(hstmt, 1, SQL_C_CHAR, (SQLPOINTER) LastName, sizeof(LastName), NULL); cliReturnCode = SQLFetch(hstmt); while (cliReturnCode != SQL_NO_DATA) { printf("%s; ", LastName); cliReturnCode = SQLFetch(hstmt); } AUSGABE ADAMSON; PIANKA; YOSHIMURA; SCOUTTEN; WALKER; BROWN; JONES; LUTZ; YAMAMOTO; JOHN; 18 Datenquellen- und Treiberattribute STATISCH § SQLGetFunctions(SQLHDBC SQLUSMALLINT SQLUSMALLINT hdbc, fFunction, *SupportedPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000612.html - Ermittelt ob eine spezifische Funktion von Datenquelle und Treiber unterstützt wird § SQLDataSources(SQLHENV SQLUSMALLINT SQLCHAR SQLSMALLINT SQLSMALLINT SQLCHAR SQLSMALLINT SQLSMALLINT henv, Direction, *ServerName, BufferLength1, *NameLength1Ptr, *Description, BufferLength2, *NameLength2Ptr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000578.html - Zeigt alle katalogisierten Datenbanken an 19 Datenquellen- und Treiberattribute (2) STATISCH § SQLGetInfo(SQLHDBC SQLUSMALLINT SQLPOINTER SQLSMALLINT SQLSMALLINT hdbc, InfoType, InfoValuePtr, BufferLength, *StringLengthPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000615.html - Allgemeine Informationen zum verbundenen DBMS - z.B. unterstützte Aggregationsfunktionen (insgesamt 165 Einzelinformationen) § SQLGetTypeInfo(SQLHSTMT SQLSMALLINT hstmt, DataType) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000626.html - Ermittelt die unterstützten Datentypen - Erzeugt SQL-Ergebnismenge 20 Datenquellen- und Treiberattribute (3) BEISPIEL SQLUSMALLINT supported; SQLCHAR dbInfoBuf[255]; SQLSMALLINT outlen; SQLGetFunctions(hdbc, SQL_API_SQLGETINFO, &supported); if (supported == SQL_TRUE) { SQLGetInfo(hdbc, SQL_DATABASE_NAME, dbInfoBuf, 255, &outlen) ; printf("Server Database Name : %s\n", dbInfoBuf); } else printf("SQLGetInfo is not supported!\n"); 21 Datenquellen- und Treiberattribute (4) DYNAMISCH § SQLGetEnvAttr(SQLHENV SQLINTEGER SQLPOINTER SQLINTEGER SQLINTEGER henv, Attribute, ValuePtr, BufferLength, *StringLengthPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000610.html - Umgebungsattribute, ODBC 2.0 oder 3.0 § SQLGetConnectAttr(SQLHDBC SQLINTEGER SQLPOINTER SQLINTEGER SQLINTEGER hdbc, Attribute, ValuePtr, BufferLength, *StringLengthPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000600.html - Verbindungsattribute, z.B. Auto-Commit, Anzahl der gleichzeitigen Verbindungen, Isolation-Level der aktuellen Verbindung 22 Datenquellen- und Treiberattribute (5) DYNAMISCH § SQLGetStmtAttr(SQLHSTMT hstmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000623.html - Anweisungattribute, z.B. Concurrency Level, Cursor-Typen § SQLSetStmtAttr(SQLHSTMT hstmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000657.html - Setzen der Anweisungsattribute 23 Datenquellen- und Treiberattribute (5) BEISPIEL (ANWEISUNGSATTRIBUTE) SQLINTEGER cursor_hold; SQLGetStmtAttr( hstmt, SQL_ATTR_CURSOR_HOLD, &cursor_hold, 0, NULL ) ; printf( "\nCursor With Hold is: " ) ; if ( cursor_hold == SQL_CURSOR_HOLD_ON ) printf( "ON\n" ) ; else printf( "OFF\n" ) ; 24 Fehlerbehandlung CLI-RÜCKGABE-CODE (INTEGERWERT) BEI FUNKTIONSAUFRUF § SQL_SUCCESS (0) - Funktion erfolgreich ausgeführt § SQL_SUCCESS_WITH_INFO (1) - Funktion erfolgreich ausgeführt (mit Warnungen) § SQL_NO_DATA (100) - Funktion erfolgreich ausgeführt - keine Daten zurück gegeben § SQL_ERROR (-1) - Funktionsausführung fehlgeschlagen § SQL_NEED_DATA (99) - Funktionsausführung fehlgeschlagen aufgrund fehlender Daten § SQL_STILL_EXECUTING (2) - Funktion noch in Ausführung § SQL_INVALID_HANDLE (-2) - Funktionsausführung fehlgeschlagen - Programmierfehler, nicht allokierter oder falscher Handle 25 Fehlerbehandlung (2) DIAGNOSEINFORMATIONEN § Erlaubt detaillierte Fehlerdiagnose § SQLSTATE - Rückgabewert jedes DB2 CLI-Funktionsaufrufs - Bestehend aus 5 alphanumerischen Zeichen „ccsss“ - Fehlerklasse (cc): • 00 = Success, 01 = Warnung, 02= No Data Found, … - Fehlerunterklasse (sss) - siehe http://publib.boulder.ibm.com/infocenter/idshelp/v111/index.jsp?topic=/com.ibm.sqls.doc/sqls548.htm § SQLGetDiagField(HandleType, Handle, RecNumber, DiagIdentifier, DiagInfoPtr, BufferLength, *StringLengthPtr) http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000608.html - Liefert Headereinträge der Diagnoseinformation § SQLGetDiagRec(HandleType, Handle, RecNumber, *SQLState, *MessageText, BufferLength, *TextLengthPtr) *NativeErrorPtr, http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000609.html - Liefert einen Eintrag der Diagnoseinformation 26 Fehlerbehandlung (3) BEISPIEL SQLCHAR SQLSTATE[6]; SQLCHAR ERRMSG[255]; CLIRC = SQLCONNECT(HDBC, (SQLCHAR *) "SAMPLE", SQL_NTS, (SQLCHAR *) "FOO", SQL_NTS, (SQLCHAR *) "BAR", SQL_NTS); IF (CLIRC != SQL_SUCCESS) { SQLGetDiagField(SQL_HANDLE_DBC, hdbc, 0, SQL_DIAG_NUMBER, &NumRecords, SQL_IS_INTEGER, NULL); for (Counter = 1; Counter <= NumRecords; Counter++) { SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, Counter, SQLState, SQLCode, ErrMsg, sizeof(ErrMsg), 0); printf("SQLSTATE : %s\n", SQLState); printf("%s\n", ErrMsg); } } Ausgabe SQLSTATE : 08001 [IBM][CLI Driver] SQL30082N Security processing failed with reason "24" ("USERNAME AND/OR PASSWORD INVALID"). SQLSTATE=08001 27 CLI-Anwendung erstellen :~> /home/dbprog/build/build-app.sh mycliapp.c Connected... 000150 ADAMSON 000160 PIANKA 000170 YOSHIMURA 000180 SCOUTTEN 000190 WALKER 000200 BROWN 000210 JONES 000220 LUTZ 200170 YAMAMOTO 200220 JOHN Disconnected. :~> bld-app-c DB2DIR=/opt/ibm/db2/V9.7 # Compile the program. gcc -I$DB2DIR/include -c $1.c # Link the program. gcc -o $1 $1.o -L$DB2DIR/lib64 -l db2 28 Zusammenfassung CLI/ODBC-ARCHITEKTUR CLI-HANDLE § Environment-Handle, Connection-Handle, Descriptor-Handle, Statement-Handle INITIALISIERUNG, TERMINIERUNG, ANFRAGEVERARBEITUNG ATTRIBUTE § Datenquellen- und Treiberattribute § Anweisungsattribute FEHLERBEHANDLUNG UND DIAGNOSE ALLE BEISPIELE LIEGEN UNTER: /HOME/DBPROG/EXAMPLES/09/ 29