| René Nyffenegger's collection of things on the web | |
|
René Nyffenegger on Oracle - Most wanted - Feedback
|
adpoci | ||
|
the first programm. All it does is connecting to a database and wait for a key to be hit. In the meantime, the session created
in the programm can be viewed in v$session
The code for the library
This library is by no means finished. I try to extend it when I have time and feel like doing so.
In order to compile them into a shared library, issue the following command:
On Linux with gcc:
gcc -Wall -I$ORACLE_HOME/rdbms/demo -I$ORACLE_HOME/rdbms/public -c -fPIC adpoci.c -o libadpoci.o gcc -shared -o libadpoci.so libadpoci.o
On Windows with mingw:
gcc -Wall -I%ORACLE_HOME%\oci\include -c adpoci.c -o adpoci.o gcc -shared -o adpoci.dll adpoci.o %ORACLE_HOME%/bin/oci.dll adpoci.hadpoci.h
#ifdef __GNUC__ # define _int64 long long #endif #ifdef __cplusplus extern "C" { #endif #include <oci.h> struct oci_connection { /* The environment handle defines a context in which all OCI functions are invoked. Each environment handle contains a memory cache, which allows for fast memory access. All memory allocation under the environment handle is done from this cache. Access to the cache is serialized if multiple threads try to allocate memory under the same environment handle. When multiple threads share a single environment handle, they may block on access to the cache. The environment handle is passed as the parent parameter to the OCIHandleAlloc() call to allocate all other handle types. Bind and define handles are allocated implicitly. */ OCIEnv* env; /* The error handle is passed as a parameter to most OCI calls. The error handle maintains information about errors that occur during an OCI operation. If an error occurs in a call, the error handle can be passed to OCIErrorGet() to obtain additional information about the error that occurred. Allocating the error handle is one of the first steps in an OCI application because most OCI calls require an error handle as one of its parameters. */ OCIError* err; OCIServer* srv; OCISvcCtx* svc; OCISession* ses; }; struct oci_description { text col_name[31]; ub2 col_type; }; void checkerr(OCIError* err, sword status, text errbuf[512]); void parse_connect_string ( char* connect_str, /* in */ text username[31], /* out */ text password[31], /* out */ text dbname [31] /* out */ ); int oci_describe( OCIStmt* sh, char* errmsg, struct oci_connection* conn, struct oci_description* descr, int pos); int oci_connect( text username[30], text password[30], text dbname [30], struct oci_connection* connection, char errmsg [512] ); int oci_parse_and_execute( char* stmt, char errmsg[512], struct oci_connection* conn ); int oci_execute0( OCIStmt* sh, char* errmsg, struct oci_connection* conn); OCIStmt* oci_parse( char* stmt, char errmsg[512], struct oci_connection* conn ); int oci_execute( OCIStmt* sh, char* errmsg, struct oci_connection* conn, int nof_binds, ...); int oci_fetch( OCIStmt* sh, char* errmsg, struct oci_connection* conn); int oci_define( OCIStmt* sh, char* errmsg, struct oci_connection* conn, int nof_defines, ...); int oci_commit(struct oci_connection* conn, char* errmsg); #ifdef __cplusplus } #endif adpoci.cadpoci.c
#include "adpoci.h" #include <string.h> #include <stdio.h> // TODO: raus #include <windows.h> static int oci_env_created = 0; int oci_connect( text username[31], text password[31], text dbname [31], struct oci_connection* conn, char errmsg[512] ) { sword r; if (!oci_env_created) { r=OCIEnvCreate( &conn->env, OCI_DEFAULT | OCI_THREADED //OCI_OBJECT //OCI_EVENTS //OCI_NO_UCB //OCI_ENV_NO_MUTEX //OCI_NEW_LENGTH_SEMANTICS , 0, 0, 0, 0, 0, 0); if (r != OCI_SUCCESS) { strcpy(errmsg,"Couldn't create environment (OCIEnvCreate"); goto clean_up; } oci_env_created = 1; } OCIHandleAlloc(conn->env, (dvoid**)&conn->err, OCI_HTYPE_ERROR, 0, 0); OCIHandleAlloc(conn->env, (dvoid**)&conn->srv, OCI_HTYPE_SERVER, 0, 0); OCIHandleAlloc(conn->env, (dvoid**)&conn->svc, OCI_HTYPE_SVCCTX, 0, 0); OCIHandleAlloc(conn->env, (dvoid**)&conn->ses, OCI_HTYPE_SESSION, 0, 0); // r = OCILogon(conn->env, conn->err, &conn->svc, // username, strlen((const char*) username), // password, strlen((const char*) password), // dbname , strlen((const char*) dbname )); r=OCIServerAttach(conn->srv, conn->err, dbname, strlen((const char*)dbname), (ub4) OCI_DEFAULT); if (r != OCI_SUCCESS) { checkerr(conn->err, r, errmsg); goto clean_up; } OCIAttrSet(conn->svc, OCI_HTYPE_SVCCTX, conn->srv, 0, OCI_ATTR_SERVER, conn->err); OCIAttrSet(conn->ses, OCI_HTYPE_SESSION, username, strlen((const char*)username), OCI_ATTR_USERNAME, conn->err); OCIAttrSet(conn->ses, OCI_HTYPE_SESSION, password, strlen((const char*)password), OCI_ATTR_PASSWORD, conn->err); if ( (r=OCIAttrSet((dvoid *) conn->svc, (ub4) OCI_HTYPE_SVCCTX, (dvoid *) conn->ses, (ub4) 0, (ub4) OCI_ATTR_SESSION, conn->err)) ) { checkerr(conn->err, r,errmsg); goto clean_up; } r=OCISessionBegin (conn->svc, conn->err, conn->ses, OCI_CRED_RDBMS, OCI_DEFAULT); if (r != OCI_SUCCESS) { checkerr(conn->err, r,errmsg); goto clean_up; } return 1; clean_up: //strcpy(errmsg,(const char*) errbuf); return 0; } void checkerr(OCIError* err, sword status, text errbuf[512]) { sb4 errcode; switch (status) { case OCI_SUCCESS: strcpy((char*)errbuf, "No error"); break; case OCI_SUCCESS_WITH_INFO: strcpy((char*)errbuf, "OCI_SUCCESS_WITH_INFO"); break; case OCI_NEED_DATA: strcpy((char*)errbuf, "OCI_NEED_DATA"); break; case OCI_NO_DATA: strcpy((char*)errbuf, "OCI_NO_DATA"); break; case OCI_ERROR: OCIErrorGet (err, (ub4) 1, (text*) NULL, &errcode, errbuf, (ub4) 512 , (ub4) OCI_HTYPE_ERROR); break; case OCI_INVALID_HANDLE: strcpy((char*)errbuf, "OCI_INVALID_HANDLE"); break; case OCI_STILL_EXECUTING: strcpy((char*)errbuf, "OCI_STILL_EXECUTING"); break; case OCI_CONTINUE: strcpy((char*)errbuf, "OCI_CONTINUE"); break; default: strcpy((char*)errbuf, "Unknown error"); break; } } void parse_connect_string( char* connect_str, /* in */ text username[31], /* out */ text password[31], /* out */ text dbname [31] /* out */ ) { username[0] = 0; password[0] = 0; dbname [0] = 0; text* to=username; while (*connect_str) { if (*connect_str == '/') { *to=0; to=password; connect_str++; continue; } if (*connect_str == '@') { *to=0; to=dbname; connect_str++; continue; } *to=*connect_str; to++; connect_str++; } *to=0; } int oci_parse_and_execute( char* stmt, char errmsg[512], struct oci_connection* conn ) { OCIStmt *sh; sword r; if ((r=OCIHandleAlloc((dvoid *) conn->env, (dvoid **) &sh, (ub4) OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0))) { checkerr(conn->err, r, (text*)errmsg); return 0; } if ((r=OCIStmtPrepare(sh, conn->err, (text*)(void*)stmt, (ub4) strlen((char *) stmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT))) { checkerr(conn->err, r, (text*)errmsg); OCIHandleFree((dvoid *) sh, (ub4) OCI_HTYPE_STMT); return 0; } if ((r=OCIStmtExecute(conn->svc, sh, conn->err, (ub4) 1, (ub4) 0, (CONST OCISnapshot *) 0, (OCISnapshot *) 0, (ub4) OCI_DEFAULT))) { checkerr(conn->err, r, (text*)errmsg); OCIHandleFree((dvoid *) sh, (ub4) OCI_HTYPE_STMT); return 0; } OCIHandleFree((dvoid *) sh, (ub4) OCI_HTYPE_STMT); return 1; } OCIStmt* oci_parse( char* stmt, char errmsg[512], struct oci_connection* conn ) { OCIStmt* sh; sword r; if (OCIHandleAlloc((dvoid *) conn->env, (dvoid **) &sh, (ub4) OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0)) { checkerr(conn->err, r, (text*)errmsg); return 0; } if ((r=OCIStmtPrepare(sh, conn->err, (text*)(void*)stmt, (ub4) strlen((char *) stmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT))) { checkerr(conn->err, r, (text*)errmsg); OCIHandleFree((dvoid *) sh, (ub4) OCI_HTYPE_STMT); return 0; } return sh; } /* VARCHAR2 char[n] SQLT_CHR NUMBER unsigned char[21] SQLT_NUM 8-bit signed INTEGER 3 signed char SQLT_INT 16-bit signed INTEGER 3 signed short, signed int SQLT_INT 32-bit signed INTEGER 3 signed int, signed long SQLT_INT FLOAT float, double SQLT_FLT Null-terminated STRING char[n+1] SQLT_STR VARNUM char[22] SQLT_VNU LONG char[n] SQLT_LNG VARCHAR char[n+sizeof(short integer)] SQLT_VCS DATE char[7] SQLT_DAT VARRAW unsigned char[n+sizeof(short integer)] SQLT_VBI RAW unsigned char[n] SQLT_BIN LONG RAW unsigned char[n] SQLT_LBI UNSIGNED INT unsigned SQLT_UIN LONG VARCHAR char[n+sizeof(integer)] SQLT_LVC LONG VARRAW unsigned char[n+sizeof(integer)] SQLT_LVB CHAR char[n] SQLT_AFC CHARZ char[n+1] SQLT_AVC ROWID descriptor OCIRowid * SQLT_RDD NAMED DATA TYPE struct SQLT_NTY REF OCIRef SQLT_REF Character LOB descriptor OCILobLocator (see note 2) SQLT_CLOB Binary LOB descriptor OCILobLocator (see note 2) SQLT_BLOB Binary FILE descriptor OCILobLocator SQLT_FILE OCI string type OCIString SQLT_VST (see note 1) OCI date type OCIDate * SQLT_ODT (see note 1) ANSI DATE descriptor OCIDateTime * SQLT_DATE TIMESTAMP descriptor OCIDateTime * SQLT_TIMESTAMP TIMESTAMP WITH TIME ZONE descriptor OCIDateTime * SQLT_TIMESTAMP_TZ INTERVAL YEAR TO MONTH descriptor OCIInterval * SQLT_INTERVAL_YM INTERVAL DAY TO SECOND descriptor OCIInterval * SQLT_INTERVAL_DS TIMESTAMP WITH LOCAL TIME ZONE descriptor OCIDateTime * SQLT_TIMESTAMP_LTZ (1) For more information on the use of these datatypes, refer to Chapter 11, "Object-Relational Datatypes". (2) In applications using datatype mappings generated by OTT, CLOBs may be mapped as OCIClobLocator, and BLOBs may be mapped as OCIBlobLocator. For more information, refer to Chapter 14, "The Object Type Translator (OTT)". */ int oci_define( OCIStmt* sh, char* errmsg, struct oci_connection* conn, int nof_defines, ...) { OCIDefine *defnp = (OCIDefine *) 0; sword r; va_list defines; dvoid* value_ptr; int sz; int pos; ub2 dt_type; va_start(defines, nof_defines); for (pos=0;pos<nof_defines; pos++) { dt_type = va_arg(defines, int); switch (dt_type) { case SQLT_INT: value_ptr=va_arg(defines, dvoid*); sz = sizeof(int); break; case SQLT_FLT: value_ptr = va_arg(defines, dvoid*); sz = sizeof(double); break; case SQLT_CHR: case SQLT_STR: value_ptr = va_arg(defines, dvoid*); sz = va_arg(defines, int); break; case SQLT_ODT: value_ptr = va_arg(defines, dvoid*); sz = sizeof(OCIDate); break; default: //"THIS MUST NOT HAPPEN"; strcpy(errmsg, "adp_oci_error 0001, datatype not yet implemented"); return 0; } if ( (r=OCIDefineByPos( sh, &defnp, conn->err, pos+1, value_ptr, sz, dt_type, (dvoid *) 0, // indp (ub2 *) 0, // rlenp (ub2 *) 0, // rcodep OCI_DEFAULT) )) { checkerr(conn->err, r, (text*)errmsg); return 0; } } return 1; } int oci_execute( OCIStmt* sh, char* errmsg, struct oci_connection* conn, int nof_binds, ...) { OCIBind *bndhp = (OCIBind*) 0; sword r; int sz; int pos; va_list binds; ub2 dt_type; dvoid* value_ptr; int i; double d; va_start(binds, nof_binds); for (pos=0;pos<nof_binds;pos++) { dt_type = va_arg(binds, int); switch (dt_type) { case SQLT_INT: i = va_arg(binds, int); sz = sizeof(int); value_ptr= &i; break; case SQLT_FLT: d = va_arg(binds, double); sz = sizeof(double); value_ptr = &d; break; case SQLT_CHR: value_ptr = va_arg(binds, char*); sz = strlen( (char*) value_ptr); break; case SQLT_ODT: value_ptr = va_arg(binds, OCIDate*); sz = sizeof(OCIDate); break; } if ((r=OCIBindByPos(sh, &bndhp, conn->err, (ub4) pos+1, // position value_ptr, // value pointer sz, // size dt_type, (dvoid *) 0, // indp (ub2 *) 0, // alenp (ub2 *) 0, // rcodep (ub4 ) 0, // maxarr_len (ub4 *) 0, // curelp (ub4) OCI_DEFAULT))) { checkerr(conn->err, r, (text*)errmsg); return 0; } } if ((r=OCIStmtExecute( conn->svc, sh, conn->err, (ub4) 1, // iters (ub4) 0, (CONST OCISnapshot *) 0, (OCISnapshot *) 0, (ub4) OCI_DEFAULT))) { checkerr(conn->err, r, (text*)errmsg); OCIHandleFree((dvoid *) sh, (ub4) OCI_HTYPE_STMT); return 0; } return 1; } /* Todo: Getting the number of columns in the query : OCIAttrGet(stmhp, OCI_HTYPE_STMT, &numcols, 0, OCI_ATTR_PARAM_COUNT, errh); */ int oci_execute0( OCIStmt* sh, char* errmsg, struct oci_connection* conn) { sword r; if ((r=OCIStmtExecute( conn->svc, sh, conn->err, (ub4) 0, // iters (ub4) 0, (CONST OCISnapshot *) 0, (OCISnapshot *) 0, (ub4) OCI_DEFAULT))) { checkerr(conn->err, r, (text*)errmsg); OCIHandleFree((dvoid *) sh, (ub4) OCI_HTYPE_STMT); return 0; } return 1; } int oci_fetch( OCIStmt* sh, char* errmsg, struct oci_connection* conn) { sb4 r; r = OCIStmtFetch( sh, conn->err, (ub4) 1, (ub4) OCI_FETCH_NEXT, (ub4) OCI_DEFAULT); if (r == OCI_SUCCESS) { return 1; } else if (r == OCI_SUCCESS_WITH_INFO) { return 1; } else { if (r != OCI_NO_DATA) { checkerr(conn->err, r, (text*)errmsg); return 0; } return 0; } } // Metalink note 125057.1 int oci_describe( OCIStmt* sh, char* errmsg, struct oci_connection* conn, struct oci_description* descr, int pos) { text* colName; OCIParam* param = 0; ub4 len; sb4 status; status = OCIParamGet(sh, OCI_HTYPE_STMT, conn->err, (void**)¶m, (ub4) pos); if (status == OCI_SUCCESS) { len = sizeof(sb2); OCIAttrGet((dvoid*)param, (ub4) OCI_DTYPE_PARAM, (dvoid*) &(descr->col_type), &len, (ub4) OCI_ATTR_DATA_TYPE, conn->err); len = sizeof(sb4); OCIAttrGet((dvoid*)param, (ub4) OCI_DTYPE_PARAM, (dvoid**)&colName , &len, (ub4) OCI_ATTR_NAME , conn->err); //printf("len: %d\n",len); //descr->col_name[len]=0; memcpy(descr->col_name, colName, len); descr->col_name[len]=0; return 1; } else { return 0; } } int oci_commit(struct oci_connection* conn, char* errmsg) { sb4 r; if ((r=OCITransCommit(conn->svc, conn->err, 0))) { checkerr(conn->err, r, (text*)errmsg); return 0; } return 1; } |