1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter/* Developed initially by Nick Kew and Chris Darroch. 18251876Speter * Contributed to the APR project by kind permission of 19251876Speter * Pearson Education Core Technology Group (CTG), 20251876Speter * formerly Central Media Group (CMG). 21251876Speter */ 22251876Speter 23251876Speter/* apr_dbd_oracle - a painful attempt 24251876Speter * 25251876Speter * Based first on the documentation at 26251876Speter * http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96584/toc.htm 27251876Speter * 28251876Speter * Those docs have a lot of internal inconsistencies, contradictions, etc 29251876Speter * So I've snarfed the demo programs (from Oracle 8, not included in 30251876Speter * the current downloadable oracle), and used code from them. 31251876Speter * 32251876Speter * Why do cdemo81.c and cdemo82.c do the same thing in very different ways? 33251876Speter * e.g. cdemo82 releases all its handle on shutdown; cdemo81 doesn't 34251876Speter * 35251876Speter * All the ORA* functions return a "sword". Some of them are documented; 36251876Speter * others aren't. So I've adopted a policy of using switch statements 37251876Speter * everywhere, even when we're not doing anything with the return values. 38251876Speter * 39251876Speter * This makes no attempt at performance tuning, such as setting 40251876Speter * prefetch cache size. We need some actual performance data 41251876Speter * to make that meaningful. Input from someone with experience 42251876Speter * as a sysop using oracle would be a good start. 43251876Speter */ 44251876Speter 45251876Speter/* shut compiler up */ 46251876Speter#ifdef DEBUG 47251876Speter#define int_errorcode int errorcode 48251876Speter#else 49251876Speter#define int_errorcode 50251876Speter#endif 51251876Speter 52251876Speter#include "apu.h" 53251876Speter 54251876Speter#if APU_HAVE_ORACLE 55251876Speter 56251876Speter#include <ctype.h> 57251876Speter#include <stdlib.h> 58251876Speter#include <stdio.h> 59251876Speter 60251876Speter#include <oci.h> 61251876Speter 62251876Speter#include "apr_strings.h" 63251876Speter#include "apr_lib.h" 64251876Speter#include "apr_time.h" 65251876Speter#include "apr_hash.h" 66251876Speter#include "apr_buckets.h" 67251876Speter 68251876Speter#define TRANS_TIMEOUT 30 69251876Speter#define MAX_ARG_LEN 256 /* in line with other apr_dbd drivers. We alloc this 70251876Speter * lots of times, so a large value gets hungry. 71251876Speter * Should really make it configurable 72251876Speter */ 73251876Speter#define DEFAULT_LONG_SIZE 4096 74251876Speter#define DBD_ORACLE_MAX_COLUMNS 256 75251876Speter#define NUMERIC_FIELD_SIZE 32 76251876Speter 77251876Speter#define CHECK_CONN_QUERY "SELECT 1 FROM dual" 78251876Speter 79251876Speter#define ERR_BUF_SIZE 200 80251876Speter 81251876Speter#ifdef DEBUG 82251876Speter#include <stdio.h> 83251876Speter#endif 84251876Speter 85251876Speter#include "apr_dbd_internal.h" 86251876Speter 87251876Speter/* declarations */ 88251876Speterstatic const char *dbd_oracle_error(apr_dbd_t *sql, int n); 89251876Speterstatic int dbd_oracle_prepare(apr_pool_t *pool, apr_dbd_t *sql, 90251876Speter const char *query, const char *label, 91251876Speter int nargs, int nvals, apr_dbd_type_e *types, 92251876Speter apr_dbd_prepared_t **statement); 93251876Speterstatic int outputParams(apr_dbd_t*, apr_dbd_prepared_t*); 94251876Speterstatic int dbd_oracle_pselect(apr_pool_t *pool, apr_dbd_t *sql, 95251876Speter apr_dbd_results_t **results, 96251876Speter apr_dbd_prepared_t *statement, 97251876Speter int seek, const char **values); 98251876Speterstatic int dbd_oracle_pquery(apr_pool_t *pool, apr_dbd_t *sql, 99251876Speter int *nrows, apr_dbd_prepared_t *statement, 100251876Speter const char **values); 101251876Speterstatic int dbd_oracle_start_transaction(apr_pool_t *pool, apr_dbd_t *sql, 102251876Speter apr_dbd_transaction_t **trans); 103251876Speterstatic int dbd_oracle_end_transaction(apr_dbd_transaction_t *trans); 104251876Speter 105251876Speterstruct apr_dbd_transaction_t { 106251876Speter int mode; 107251876Speter enum { TRANS_NONE, TRANS_ERROR, TRANS_1, TRANS_2 } status; 108251876Speter apr_dbd_t *handle; 109251876Speter OCITrans *trans; 110251876Speter OCISnapshot *snapshot1; 111251876Speter OCISnapshot *snapshot2; 112251876Speter}; 113251876Speter 114251876Speterstruct apr_dbd_results_t { 115251876Speter apr_pool_t *pool; 116251876Speter apr_dbd_t* handle; 117251876Speter unsigned int rownum; 118251876Speter int seek; 119251876Speter int nrows; 120251876Speter apr_dbd_prepared_t *statement; 121251876Speter}; 122251876Speter 123251876Speterstruct apr_dbd_t { 124251876Speter sword status; 125251876Speter OCIError *err; 126251876Speter OCIServer *svr; 127251876Speter OCISvcCtx *svc; 128251876Speter OCISession *auth; 129251876Speter apr_dbd_transaction_t* trans; 130251876Speter apr_pool_t *pool; 131251876Speter char buf[ERR_BUF_SIZE]; /* for error messages */ 132251876Speter apr_size_t long_size; 133251876Speter apr_dbd_prepared_t *check_conn_stmt; 134251876Speter}; 135251876Speter 136251876Speterstruct apr_dbd_row_t { 137251876Speter int n; 138251876Speter apr_dbd_results_t *res; 139251876Speter apr_pool_t *pool; 140251876Speter}; 141251876Speter 142251876Spetertypedef struct { 143251876Speter apr_dbd_type_e type; 144251876Speter sb2 ind; 145251876Speter sb4 len; 146251876Speter OCIBind *bind; 147251876Speter union { 148251876Speter void *raw; 149251876Speter char *sval; 150251876Speter int ival; 151251876Speter unsigned int uval; 152251876Speter double fval; 153251876Speter OCILobLocator *lobval; 154251876Speter } value; 155251876Speter} bind_arg; 156251876Speter 157251876Spetertypedef struct { 158251876Speter int type; 159251876Speter sb2 ind; 160251876Speter ub2 len; /* length of actual output */ 161251876Speter OCIDefine *defn; 162251876Speter apr_size_t sz; /* length of buf for output */ 163251876Speter union { 164251876Speter void *raw; 165251876Speter char *sval; 166251876Speter OCILobLocator *lobval; 167251876Speter } buf; 168251876Speter const char *name; 169251876Speter} define_arg; 170251876Speter 171251876Speterstruct apr_dbd_prepared_t { 172251876Speter OCIStmt *stmt; 173251876Speter int nargs; 174251876Speter int nvals; 175251876Speter bind_arg *args; 176251876Speter int nout; 177251876Speter define_arg *out; 178251876Speter apr_dbd_t *handle; 179251876Speter apr_pool_t *pool; 180251876Speter ub2 type; 181251876Speter}; 182251876Speter 183251876Speter/* AFAICT from the docs, the OCIEnv thingey can be used async 184251876Speter * across threads, so lets have a global one. 185251876Speter * 186251876Speter * We'll need shorter-lived envs to deal with requests and connections 187251876Speter * 188251876Speter * Hmmm, that doesn't work: we don't have a usermem framework. 189251876Speter * OK, forget about using APR pools here, until we figure out 190251876Speter * the right way to do it (if such a thing exists). 191251876Speter */ 192251876Speterstatic OCIEnv *dbd_oracle_env = NULL; 193251876Speter 194251876Speter/* Oracle specific bucket for BLOB/CLOB types */ 195251876Spetertypedef struct apr_bucket_lob apr_bucket_lob; 196251876Speter/** 197251876Speter * A bucket referring to a Oracle BLOB/CLOB 198251876Speter */ 199251876Speterstruct apr_bucket_lob { 200251876Speter /** Number of buckets using this memory */ 201251876Speter apr_bucket_refcount refcount; 202251876Speter /** The row this bucket refers to */ 203251876Speter const apr_dbd_row_t *row; 204251876Speter /** The column this bucket refers to */ 205251876Speter int col; 206251876Speter /** The pool into which any needed structures should 207251876Speter * be created while reading from this bucket */ 208251876Speter apr_pool_t *readpool; 209251876Speter}; 210251876Speter 211251876Speterstatic void lob_bucket_destroy(void *data); 212251876Speterstatic apr_status_t lob_bucket_read(apr_bucket *e, const char **str, 213251876Speter apr_size_t *len, apr_read_type_e block); 214251876Speterstatic apr_bucket *apr_bucket_lob_make(apr_bucket *b, 215251876Speter const apr_dbd_row_t *row, int col, 216251876Speter apr_off_t offset, apr_size_t len, 217251876Speter apr_pool_t *p); 218251876Speterstatic apr_bucket *apr_bucket_lob_create(const apr_dbd_row_t *row, int col, 219251876Speter apr_off_t offset, 220251876Speter apr_size_t len, apr_pool_t *p, 221251876Speter apr_bucket_alloc_t *list); 222251876Speter 223251876Speterstatic const apr_bucket_type_t apr_bucket_type_lob = { 224251876Speter "LOB", 5, APR_BUCKET_DATA, 225251876Speter lob_bucket_destroy, 226251876Speter lob_bucket_read, 227251876Speter apr_bucket_setaside_notimpl, 228251876Speter apr_bucket_shared_split, 229251876Speter apr_bucket_shared_copy 230251876Speter}; 231251876Speter 232251876Speterstatic void lob_bucket_destroy(void *data) 233251876Speter{ 234251876Speter apr_bucket_lob *f = data; 235251876Speter 236251876Speter if (apr_bucket_shared_destroy(f)) { 237251876Speter /* no need to destroy database objects here; it will get 238251876Speter * done automatically when the pool gets cleaned up */ 239251876Speter apr_bucket_free(f); 240251876Speter } 241251876Speter} 242251876Speter 243251876Speterstatic apr_status_t lob_bucket_read(apr_bucket *e, const char **str, 244251876Speter apr_size_t *len, apr_read_type_e block) 245251876Speter{ 246251876Speter apr_bucket_lob *a = e->data; 247251876Speter const apr_dbd_row_t *row = a->row; 248251876Speter apr_dbd_results_t *res = row->res; 249251876Speter int col = a->col; 250251876Speter apr_bucket *b = NULL; 251251876Speter apr_size_t blength = e->length; /* bytes remaining in file past offset */ 252251876Speter apr_off_t boffset = e->start; 253251876Speter define_arg *val = &res->statement->out[col]; 254251876Speter apr_dbd_t *sql = res->handle; 255251876Speter/* Only with 10g, unfortunately 256251876Speter oraub8 length = APR_BUCKET_BUFF_SIZE; 257251876Speter*/ 258251876Speter ub4 length = APR_BUCKET_BUFF_SIZE; 259251876Speter char *buf = NULL; 260251876Speter 261251876Speter *str = NULL; /* in case we die prematurely */ 262251876Speter 263251876Speter /* fetch from offset if not at the beginning */ 264251876Speter buf = apr_palloc(row->pool, APR_BUCKET_BUFF_SIZE); 265251876Speter sql->status = OCILobRead(sql->svc, sql->err, val->buf.lobval, 266251876Speter &length, 1 + (size_t)boffset, 267251876Speter (dvoid*) buf, APR_BUCKET_BUFF_SIZE, 268251876Speter NULL, NULL, 0, SQLCS_IMPLICIT); 269251876Speter/* Only with 10g, unfortunately 270251876Speter sql->status = OCILobRead2(sql->svc, sql->err, val->buf.lobval, 271251876Speter &length, NULL, 1 + boffset, 272251876Speter (dvoid*) buf, APR_BUCKET_BUFF_SIZE, 273251876Speter OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT); 274251876Speter*/ 275251876Speter if (sql->status != OCI_SUCCESS) { 276251876Speter return APR_EGENERAL; 277251876Speter } 278251876Speter blength -= length; 279251876Speter *len = length; 280251876Speter *str = buf; 281251876Speter 282251876Speter /* 283251876Speter * Change the current bucket to refer to what we read, 284251876Speter * even if we read nothing because we hit EOF. 285251876Speter */ 286251876Speter apr_bucket_pool_make(e, *str, *len, res->pool); 287251876Speter 288251876Speter /* If we have more to read from the field, then create another bucket */ 289251876Speter if (blength > 0) { 290251876Speter /* for efficiency, we can just build a new apr_bucket struct 291251876Speter * to wrap around the existing LOB bucket */ 292251876Speter b = apr_bucket_alloc(sizeof(*b), e->list); 293251876Speter b->start = boffset + *len; 294251876Speter b->length = blength; 295251876Speter b->data = a; 296251876Speter b->type = &apr_bucket_type_lob; 297251876Speter b->free = apr_bucket_free; 298251876Speter b->list = e->list; 299251876Speter APR_BUCKET_INSERT_AFTER(e, b); 300251876Speter } 301251876Speter else { 302251876Speter lob_bucket_destroy(a); 303251876Speter } 304251876Speter 305251876Speter return APR_SUCCESS; 306251876Speter} 307251876Speter 308251876Speterstatic apr_bucket *apr_bucket_lob_make(apr_bucket *b, 309251876Speter const apr_dbd_row_t *row, int col, 310251876Speter apr_off_t offset, apr_size_t len, 311251876Speter apr_pool_t *p) 312251876Speter{ 313251876Speter apr_bucket_lob *f; 314251876Speter 315251876Speter f = apr_bucket_alloc(sizeof(*f), b->list); 316251876Speter f->row = row; 317251876Speter f->col = col; 318251876Speter f->readpool = p; 319251876Speter 320251876Speter b = apr_bucket_shared_make(b, f, offset, len); 321251876Speter b->type = &apr_bucket_type_lob; 322251876Speter 323251876Speter return b; 324251876Speter} 325251876Speter 326251876Speterstatic apr_bucket *apr_bucket_lob_create(const apr_dbd_row_t *row, int col, 327251876Speter apr_off_t offset, 328251876Speter apr_size_t len, apr_pool_t *p, 329251876Speter apr_bucket_alloc_t *list) 330251876Speter{ 331251876Speter apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); 332251876Speter 333251876Speter APR_BUCKET_INIT(b); 334251876Speter b->free = apr_bucket_free; 335251876Speter b->list = list; 336251876Speter return apr_bucket_lob_make(b, row, col, offset, len, p); 337251876Speter} 338251876Speter 339251876Speterstatic apr_status_t dbd_free_lobdesc(void *lob) 340251876Speter{ 341251876Speter switch (OCIDescriptorFree(lob, OCI_DTYPE_LOB)) { 342251876Speter case OCI_SUCCESS: 343251876Speter return APR_SUCCESS; 344251876Speter default: 345251876Speter return APR_EGENERAL; 346251876Speter } 347251876Speter} 348251876Speter 349251876Speterstatic apr_status_t dbd_free_snapshot(void *snap) 350251876Speter{ 351251876Speter switch (OCIDescriptorFree(snap, OCI_DTYPE_SNAP)) { 352251876Speter case OCI_SUCCESS: 353251876Speter return APR_SUCCESS; 354251876Speter default: 355251876Speter return APR_EGENERAL; 356251876Speter } 357251876Speter} 358251876Speter 359251876Speterstatic void dbd_oracle_init(apr_pool_t *pool) 360251876Speter{ 361251876Speter if (dbd_oracle_env == NULL) { 362251876Speter /* Sadly, OCI_SHARED seems to be impossible to use, due to 363251876Speter * various Oracle bugs. See, for example, Oracle MetaLink bug 2972890 364251876Speter * and PHP bug http://bugs.php.net/bug.php?id=23733 365251876Speter */ 366251876Speter#ifdef OCI_NEW_LENGTH_SEMANTICS 367251876Speter OCIEnvCreate(&dbd_oracle_env, OCI_THREADED|OCI_NEW_LENGTH_SEMANTICS, 368251876Speter NULL, NULL, NULL, NULL, 0, NULL); 369251876Speter#else 370251876Speter OCIEnvCreate(&dbd_oracle_env, OCI_THREADED, 371251876Speter NULL, NULL, NULL, NULL, 0, NULL); 372251876Speter#endif 373251876Speter } 374251876Speter} 375251876Speter 376251876Speterstatic apr_dbd_t *dbd_oracle_open(apr_pool_t *pool, const char *params, 377251876Speter const char **error) 378251876Speter{ 379251876Speter apr_dbd_t *ret = apr_pcalloc(pool, sizeof(apr_dbd_t)); 380251876Speter int errorcode; 381251876Speter 382251876Speter char *BLANK = ""; 383251876Speter struct { 384251876Speter const char *field; 385251876Speter char *value; 386251876Speter } fields[] = { 387251876Speter {"user", BLANK}, 388251876Speter {"pass", BLANK}, 389251876Speter {"dbname", BLANK}, 390251876Speter {"server", BLANK}, 391251876Speter {NULL, NULL} 392251876Speter }; 393251876Speter int i; 394251876Speter const char *ptr; 395251876Speter const char *key; 396251876Speter size_t klen; 397251876Speter const char *value; 398251876Speter size_t vlen; 399251876Speter static const char *const delims = " \r\n\t;|,"; 400251876Speter 401251876Speter ret->pool = pool; 402251876Speter ret->long_size = DEFAULT_LONG_SIZE; 403251876Speter 404251876Speter /* snitch parsing from the MySQL driver */ 405251876Speter for (ptr = strchr(params, '='); ptr; ptr = strchr(ptr, '=')) { 406251876Speter /* don't dereference memory that may not belong to us */ 407251876Speter if (ptr == params) { 408251876Speter ++ptr; 409251876Speter continue; 410251876Speter } 411251876Speter for (key = ptr-1; apr_isspace(*key); --key); 412251876Speter klen = 0; 413251876Speter while (apr_isalpha(*key)) { 414251876Speter if (key == params) { 415251876Speter /* Don't parse off the front of the params */ 416251876Speter --key; 417251876Speter ++klen; 418251876Speter break; 419251876Speter } 420251876Speter --key; 421251876Speter ++klen; 422251876Speter } 423251876Speter ++key; 424251876Speter for (value = ptr+1; apr_isspace(*value); ++value); 425251876Speter vlen = strcspn(value, delims); 426251876Speter for (i=0; fields[i].field != NULL; ++i) { 427251876Speter if (!strncasecmp(fields[i].field, key, klen)) { 428251876Speter fields[i].value = apr_pstrndup(pool, value, vlen); 429251876Speter break; 430251876Speter } 431251876Speter } 432251876Speter ptr = value+vlen; 433251876Speter } 434251876Speter 435251876Speter ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->err, 436251876Speter OCI_HTYPE_ERROR, 0, NULL); 437251876Speter switch (ret->status) { 438251876Speter default: 439251876Speter#ifdef DEBUG 440251876Speter printf("ret->status is %d\n", ret->status); 441251876Speter break; 442251876Speter#else 443251876Speter return NULL; 444251876Speter#endif 445251876Speter case OCI_SUCCESS: 446251876Speter break; 447251876Speter } 448251876Speter 449251876Speter ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->svr, 450251876Speter OCI_HTYPE_SERVER, 0, NULL); 451251876Speter switch (ret->status) { 452251876Speter default: 453251876Speter#ifdef DEBUG 454251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 455251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 456251876Speter printf("OPEN ERROR %d (alloc svr): %s\n", ret->status, ret->buf); 457251876Speter break; 458251876Speter#else 459251876Speter if (error) { 460251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 461251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 462251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 463251876Speter } 464251876Speter return NULL; 465251876Speter#endif 466251876Speter case OCI_SUCCESS: 467251876Speter break; 468251876Speter } 469251876Speter 470251876Speter ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->svc, 471251876Speter OCI_HTYPE_SVCCTX, 0, NULL); 472251876Speter switch (ret->status) { 473251876Speter default: 474251876Speter#ifdef DEBUG 475251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 476251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 477251876Speter printf("OPEN ERROR %d (alloc svc): %s\n", ret->status, ret->buf); 478251876Speter break; 479251876Speter#else 480251876Speter if (error) { 481251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 482251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 483251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 484251876Speter } 485251876Speter return NULL; 486251876Speter#endif 487251876Speter case OCI_SUCCESS: 488251876Speter break; 489251876Speter } 490251876Speter 491251876Speter/* All the examples use the #else */ 492251876Speter#if CAN_DO_LOGIN 493251876Speter ret->status = OCILogon(dbd_oracle_env, ret->err, &ret->svc, fields[0].value, 494251876Speter strlen(fields[0].value), fields[1].value, 495251876Speter strlen(fields[1].value), fields[2].value, 496251876Speter strlen(fields[2].value)); 497251876Speter switch (ret->status) { 498251876Speter default: 499251876Speter#ifdef DEBUG 500251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 501251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 502251876Speter printf("OPEN ERROR: %s\n", ret->buf); 503251876Speter break; 504251876Speter#else 505251876Speter if (error) { 506251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 507251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 508251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 509251876Speter } 510251876Speter return NULL; 511251876Speter#endif 512251876Speter case OCI_SUCCESS: 513251876Speter break; 514251876Speter } 515251876Speter#else 516251876Speter ret->status = OCIServerAttach(ret->svr, ret->err, (text*) fields[3].value, 517251876Speter strlen(fields[3].value), OCI_DEFAULT); 518251876Speter switch (ret->status) { 519251876Speter default: 520251876Speter#ifdef DEBUG 521251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 522251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 523251876Speter printf("OPEN ERROR %d (server attach): %s\n", ret->status, ret->buf); 524251876Speter break; 525251876Speter#else 526251876Speter if (error) { 527251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 528251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 529251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 530251876Speter } 531251876Speter return NULL; 532251876Speter#endif 533251876Speter case OCI_SUCCESS: 534251876Speter break; 535251876Speter } 536251876Speter ret->status = OCIAttrSet(ret->svc, OCI_HTYPE_SVCCTX, ret->svr, 0, 537251876Speter OCI_ATTR_SERVER, ret->err); 538251876Speter switch (ret->status) { 539251876Speter default: 540251876Speter#ifdef DEBUG 541251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 542251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 543251876Speter printf("OPEN ERROR %d (attr set): %s\n", ret->status, ret->buf); 544251876Speter break; 545251876Speter#else 546251876Speter if (error) { 547251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 548251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 549251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 550251876Speter } 551251876Speter return NULL; 552251876Speter#endif 553251876Speter case OCI_SUCCESS: 554251876Speter break; 555251876Speter } 556251876Speter ret->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**)&ret->auth, 557251876Speter OCI_HTYPE_SESSION, 0, NULL); 558251876Speter switch (ret->status) { 559251876Speter default: 560251876Speter#ifdef DEBUG 561251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 562251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 563251876Speter printf("OPEN ERROR %d (alloc auth): %s\n", ret->status, ret->buf); 564251876Speter break; 565251876Speter#else 566251876Speter if (error) { 567251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 568251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 569251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 570251876Speter } 571251876Speter return NULL; 572251876Speter#endif 573251876Speter case OCI_SUCCESS: 574251876Speter break; 575251876Speter } 576251876Speter ret->status = OCIAttrSet(ret->auth, OCI_HTYPE_SESSION, fields[0].value, 577251876Speter strlen(fields[0].value), OCI_ATTR_USERNAME, ret->err); 578251876Speter switch (ret->status) { 579251876Speter default: 580251876Speter#ifdef DEBUG 581251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 582251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 583251876Speter printf("OPEN ERROR %d (attr username): %s\n", ret->status, ret->buf); 584251876Speter break; 585251876Speter#else 586251876Speter if (error) { 587251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 588251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 589251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 590251876Speter } 591251876Speter return NULL; 592251876Speter#endif 593251876Speter case OCI_SUCCESS: 594251876Speter break; 595251876Speter } 596251876Speter ret->status = OCIAttrSet(ret->auth, OCI_HTYPE_SESSION, fields[1].value, 597251876Speter strlen(fields[1].value), OCI_ATTR_PASSWORD, ret->err); 598251876Speter switch (ret->status) { 599251876Speter default: 600251876Speter#ifdef DEBUG 601251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 602251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 603251876Speter printf("OPEN ERROR %d (attr password): %s\n", ret->status, ret->buf); 604251876Speter break; 605251876Speter#else 606251876Speter if (error) { 607251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 608251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 609251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 610251876Speter } 611251876Speter return NULL; 612251876Speter#endif 613251876Speter case OCI_SUCCESS: 614251876Speter break; 615251876Speter } 616251876Speter ret->status = OCISessionBegin(ret->svc, ret->err, ret->auth, 617251876Speter OCI_CRED_RDBMS, OCI_DEFAULT); 618251876Speter switch (ret->status) { 619251876Speter default: 620251876Speter#ifdef DEBUG 621251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 622251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 623251876Speter printf("OPEN ERROR %d (session begin): %s\n", ret->status, ret->buf); 624251876Speter break; 625251876Speter#else 626251876Speter if (error) { 627251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 628251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 629251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 630251876Speter } 631251876Speter return NULL; 632251876Speter#endif 633251876Speter case OCI_SUCCESS: 634251876Speter break; 635251876Speter } 636251876Speter ret->status = OCIAttrSet(ret->svc, OCI_HTYPE_SVCCTX, ret->auth, 0, 637251876Speter OCI_ATTR_SESSION, ret->err); 638251876Speter switch (ret->status) { 639251876Speter default: 640251876Speter#ifdef DEBUG 641251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, ret->buf, 642251876Speter sizeof(ret->buf), OCI_HTYPE_ERROR); 643251876Speter printf("OPEN ERROR %d (attr session): %s\n", ret->status, ret->buf); 644251876Speter#else 645251876Speter if (error) { 646251876Speter *error = apr_pcalloc(pool, ERR_BUF_SIZE); 647251876Speter OCIErrorGet(ret->err, 1, NULL, &errorcode, (unsigned char*)(*error), 648251876Speter ERR_BUF_SIZE, OCI_HTYPE_ERROR); 649251876Speter } 650251876Speter return NULL; 651251876Speter#endif 652251876Speter break; 653251876Speter case OCI_SUCCESS: 654251876Speter break; 655251876Speter } 656251876Speter#endif 657251876Speter 658251876Speter if(dbd_oracle_prepare(pool, ret, CHECK_CONN_QUERY, NULL, 0, 0, NULL, 659251876Speter &ret->check_conn_stmt) != 0) { 660251876Speter return NULL; 661251876Speter } 662251876Speter 663251876Speter return ret; 664251876Speter} 665251876Speter 666251876Speter#ifdef EXPORT_NATIVE_FUNCS 667251876Speterstatic apr_size_t dbd_oracle_long_size_set(apr_dbd_t *sql, 668251876Speter apr_size_t long_size) 669251876Speter{ 670251876Speter apr_size_t old_size = sql->long_size; 671251876Speter sql->long_size = long_size; 672251876Speter return old_size; 673251876Speter} 674251876Speter#endif 675251876Speter 676251876Speterstatic const char *dbd_oracle_get_name(const apr_dbd_results_t *res, int n) 677251876Speter{ 678251876Speter define_arg *val = &res->statement->out[n]; 679251876Speter 680251876Speter if ((n < 0) || (n >= res->statement->nout)) { 681251876Speter return NULL; 682251876Speter } 683251876Speter return val->name; 684251876Speter} 685251876Speter 686251876Speterstatic int dbd_oracle_get_row(apr_pool_t *pool, apr_dbd_results_t *res, 687251876Speter apr_dbd_row_t **rowp, int rownum) 688251876Speter{ 689251876Speter apr_dbd_row_t *row = *rowp; 690251876Speter apr_dbd_t *sql = res->handle; 691251876Speter int_errorcode; 692251876Speter 693251876Speter if (row == NULL) { 694251876Speter row = apr_palloc(pool, sizeof(apr_dbd_row_t)); 695251876Speter *rowp = row; 696251876Speter row->res = res; 697251876Speter /* Oracle starts counting at 1 according to the docs */ 698251876Speter row->n = res->seek ? rownum : 1; 699251876Speter row->pool = pool; 700251876Speter } 701251876Speter else { 702251876Speter if (res->seek) { 703251876Speter row->n = rownum; 704251876Speter } 705251876Speter else { 706251876Speter ++row->n; 707251876Speter } 708251876Speter } 709251876Speter 710251876Speter if (res->seek) { 711251876Speter sql->status = OCIStmtFetch2(res->statement->stmt, res->handle->err, 1, 712251876Speter OCI_FETCH_ABSOLUTE, row->n, OCI_DEFAULT); 713251876Speter } 714251876Speter else { 715251876Speter sql->status = OCIStmtFetch2(res->statement->stmt, res->handle->err, 1, 716251876Speter OCI_FETCH_NEXT, 0, OCI_DEFAULT); 717251876Speter } 718251876Speter switch (sql->status) { 719251876Speter case OCI_SUCCESS: 720251876Speter (*rowp)->res = res; 721251876Speter return 0; 722251876Speter case OCI_NO_DATA: 723251876Speter return -1; 724251876Speter case OCI_ERROR: 725251876Speter#ifdef DEBUG 726251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 727251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 728251876Speter printf("Execute error %d: %s\n", sql->status, sql->buf); 729251876Speter#endif 730251876Speter /* fallthrough */ 731251876Speter default: 732251876Speter return 1; 733251876Speter } 734251876Speter return 0; 735251876Speter} 736251876Speter 737251876Speterstatic const char *dbd_oracle_error(apr_dbd_t *sql, int n) 738251876Speter{ 739251876Speter /* This is ugly. Needs us to pass in a buffer of unknown size. 740251876Speter * Either we put it on the handle, or we have to keep allocing/copying 741251876Speter */ 742251876Speter sb4 errorcode; 743251876Speter 744251876Speter switch (sql->status) { 745251876Speter case OCI_SUCCESS: 746251876Speter return "OCI_SUCCESS"; 747251876Speter case OCI_SUCCESS_WITH_INFO: 748251876Speter return "OCI_SUCCESS_WITH_INFO"; 749251876Speter case OCI_NEED_DATA: 750251876Speter return "OCI_NEED_DATA"; 751251876Speter case OCI_NO_DATA: 752251876Speter return "OCI_NO_DATA"; 753251876Speter case OCI_INVALID_HANDLE: 754251876Speter return "OCI_INVALID_HANDLE"; 755251876Speter case OCI_STILL_EXECUTING: 756251876Speter return "OCI_STILL_EXECUTING"; 757251876Speter case OCI_CONTINUE: 758251876Speter return "OCI_CONTINUE"; 759251876Speter } 760251876Speter 761251876Speter switch (OCIErrorGet(sql->err, 1, NULL, &errorcode, 762251876Speter (text*) sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR)) { 763251876Speter case OCI_SUCCESS: 764251876Speter return sql->buf; 765251876Speter default: 766251876Speter return "internal error: OCIErrorGet failed"; 767251876Speter } 768251876Speter} 769251876Speter 770251876Speterstatic apr_status_t freeStatement(void *statement) 771251876Speter{ 772251876Speter int rv = APR_SUCCESS; 773251876Speter OCIStmt *stmt = ((apr_dbd_prepared_t*)statement)->stmt; 774251876Speter 775251876Speter#ifdef PREPARE2 776251876Speter OCIError *err; 777251876Speter 778251876Speter if (OCIHandleAlloc(dbd_oracle_env, (dvoid**)&err, OCI_HTYPE_ERROR, 779251876Speter 0, NULL) != OCI_SUCCESS) { 780251876Speter return APR_EGENERAL; 781251876Speter } 782251876Speter if (OCIStmtRelease(stmt, err, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS) { 783251876Speter rv = APR_EGENERAL; 784251876Speter } 785251876Speter if (OCIHandleFree(err, OCI_HTYPE_ERROR) != OCI_SUCCESS) { 786251876Speter rv = APR_EGENERAL; 787251876Speter } 788251876Speter#else 789251876Speter if (OCIHandleFree(stmt, OCI_HTYPE_STMT) != OCI_SUCCESS) { 790251876Speter rv = APR_EGENERAL; 791251876Speter } 792251876Speter#endif 793251876Speter 794251876Speter return rv; 795251876Speter} 796251876Speter 797251876Speterstatic int dbd_oracle_select(apr_pool_t *pool, apr_dbd_t *sql, 798251876Speter apr_dbd_results_t **results, 799251876Speter const char *query, int seek) 800251876Speter{ 801251876Speter int ret = 0; 802251876Speter apr_dbd_prepared_t *statement = NULL; 803251876Speter 804251876Speter ret = dbd_oracle_prepare(pool, sql, query, NULL, 0, 0, NULL, &statement); 805251876Speter if (ret != 0) { 806251876Speter return ret; 807251876Speter } 808251876Speter 809251876Speter ret = dbd_oracle_pselect(pool, sql, results, statement, seek, NULL); 810251876Speter if (ret != 0) { 811251876Speter return ret; 812251876Speter } 813251876Speter 814251876Speter return ret; 815251876Speter} 816251876Speter 817251876Speterstatic int dbd_oracle_query(apr_dbd_t *sql, int *nrows, const char *query) 818251876Speter{ 819251876Speter int ret = 0; 820251876Speter apr_pool_t *pool; 821251876Speter apr_dbd_prepared_t *statement = NULL; 822251876Speter 823251876Speter if (sql->trans && sql->trans->status == TRANS_ERROR) { 824251876Speter return 1; 825251876Speter } 826251876Speter 827251876Speter /* make our own pool so that APR allocations don't linger and so that 828251876Speter * both Stmt and LOB handles are cleaned up (LOB handles may be 829251876Speter * allocated when preparing APR_DBD_TYPE_CLOB/BLOBs) 830251876Speter */ 831251876Speter apr_pool_create(&pool, sql->pool); 832251876Speter 833251876Speter ret = dbd_oracle_prepare(pool, sql, query, NULL, 0, 0, NULL, &statement); 834251876Speter if (ret == 0) { 835251876Speter ret = dbd_oracle_pquery(pool, sql, nrows, statement, NULL); 836251876Speter if (ret == 0) { 837251876Speter sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT, 838251876Speter nrows, 0, OCI_ATTR_ROW_COUNT, 839251876Speter sql->err); 840251876Speter } 841251876Speter } 842251876Speter 843251876Speter apr_pool_destroy(pool); 844251876Speter 845251876Speter return ret; 846251876Speter} 847251876Speter 848251876Speterstatic const char *dbd_oracle_escape(apr_pool_t *pool, const char *arg, 849251876Speter apr_dbd_t *sql) 850251876Speter{ 851251876Speter return arg; /* OCI has no concept of string escape */ 852251876Speter} 853251876Speter 854251876Speterstatic int dbd_oracle_prepare(apr_pool_t *pool, apr_dbd_t *sql, 855251876Speter const char *query, const char *label, 856251876Speter int nargs, int nvals, apr_dbd_type_e *types, 857251876Speter apr_dbd_prepared_t **statement) 858251876Speter{ 859251876Speter int ret = 0; 860251876Speter int i; 861251876Speter apr_dbd_prepared_t *stmt ; 862251876Speter 863251876Speter if (*statement == NULL) { 864251876Speter *statement = apr_pcalloc(pool, sizeof(apr_dbd_prepared_t)); 865251876Speter } 866251876Speter stmt = *statement; 867251876Speter stmt->handle = sql; 868251876Speter stmt->pool = pool; 869251876Speter stmt->nargs = nargs; 870251876Speter stmt->nvals = nvals; 871251876Speter 872251876Speter /* populate our own args, if any */ 873251876Speter if (nargs > 0) { 874251876Speter stmt->args = apr_pcalloc(pool, nargs*sizeof(bind_arg)); 875251876Speter for (i = 0; i < nargs; i++) { 876251876Speter stmt->args[i].type = types[i]; 877251876Speter } 878251876Speter } 879251876Speter 880251876Speter sql->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**) &stmt->stmt, 881251876Speter OCI_HTYPE_STMT, 0, NULL); 882251876Speter if (sql->status != OCI_SUCCESS) { 883251876Speter return 1; 884251876Speter } 885251876Speter 886251876Speter sql->status = OCIStmtPrepare(stmt->stmt, sql->err, (text*) query, 887251876Speter strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT); 888251876Speter if (sql->status != OCI_SUCCESS) { 889251876Speter OCIHandleFree(stmt->stmt, OCI_HTYPE_STMT); 890251876Speter return 1; 891251876Speter } 892251876Speter 893251876Speter apr_pool_cleanup_register(pool, stmt, freeStatement, 894251876Speter apr_pool_cleanup_null); 895251876Speter 896251876Speter /* Perl gets statement type here */ 897251876Speter sql->status = OCIAttrGet(stmt->stmt, OCI_HTYPE_STMT, &stmt->type, 0, 898251876Speter OCI_ATTR_STMT_TYPE, sql->err); 899251876Speter if (sql->status != OCI_SUCCESS) { 900251876Speter return 1; 901251876Speter } 902251876Speter 903251876Speter/* Perl sets PREFETCH_MEMORY here, but the docs say there's a working default */ 904251876Speter#if 0 905251876Speter sql->status = OCIAttrSet(stmt->stmt, OCI_HTYPE_STMT, &prefetch_size, 906251876Speter sizeof(prefetch_size), OCI_ATTR_PREFETCH_MEMORY, 907251876Speter sql->err); 908251876Speter if (sql->status != OCI_SUCCESS) { 909251876Speter return 1; 910251876Speter } 911251876Speter#endif 912251876Speter 913251876Speter if (stmt->type == OCI_STMT_SELECT) { 914251876Speter ret = outputParams(sql, stmt); 915251876Speter } 916251876Speter return ret; 917251876Speter} 918251876Speter 919251876Speterstatic void dbd_oracle_bind(apr_dbd_prepared_t *statement, const char **values) 920251876Speter{ 921251876Speter OCIStmt *stmt = statement->stmt; 922251876Speter apr_dbd_t *sql = statement->handle; 923251876Speter int i, j; 924251876Speter sb2 null_ind = -1; 925251876Speter 926251876Speter for (i = 0, j = 0; i < statement->nargs; i++, j++) { 927251876Speter if (values[j] == NULL) { 928251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 929251876Speter sql->err, i + 1, 930251876Speter NULL, 0, SQLT_STR, 931251876Speter &null_ind, NULL, 932251876Speter (ub2) 0, (ub4) 0, 933251876Speter (ub4 *) 0, OCI_DEFAULT); 934251876Speter } 935251876Speter else { 936251876Speter switch (statement->args[i].type) { 937251876Speter case APR_DBD_TYPE_BLOB: 938251876Speter { 939251876Speter char *data = (char *)values[j]; 940251876Speter int size = atoi((char*)values[++j]); 941251876Speter 942251876Speter /* skip table and column for now */ 943251876Speter j += 2; 944251876Speter 945251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 946251876Speter sql->err, i + 1, 947251876Speter data, size, SQLT_LBI, 948251876Speter &statement->args[i].ind, 949251876Speter NULL, 950251876Speter (ub2) 0, (ub4) 0, 951251876Speter (ub4 *) 0, OCI_DEFAULT); 952251876Speter } 953251876Speter break; 954251876Speter case APR_DBD_TYPE_CLOB: 955251876Speter { 956251876Speter char *data = (char *)values[j]; 957251876Speter int size = atoi((char*)values[++j]); 958251876Speter 959251876Speter /* skip table and column for now */ 960251876Speter j += 2; 961251876Speter 962251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 963251876Speter sql->err, i + 1, 964251876Speter data, size, SQLT_LNG, 965251876Speter &statement->args[i].ind, 966251876Speter NULL, 967251876Speter (ub2) 0, (ub4) 0, 968251876Speter (ub4 *) 0, OCI_DEFAULT); 969251876Speter } 970251876Speter break; 971251876Speter default: 972251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 973251876Speter sql->err, i + 1, 974251876Speter (dvoid*) values[j], 975251876Speter strlen(values[j]) + 1, 976251876Speter SQLT_STR, 977251876Speter &statement->args[i].ind, 978251876Speter NULL, 979251876Speter (ub2) 0, (ub4) 0, 980251876Speter (ub4 *) 0, OCI_DEFAULT); 981251876Speter break; 982251876Speter } 983251876Speter } 984251876Speter 985251876Speter if (sql->status != OCI_SUCCESS) { 986251876Speter return; 987251876Speter } 988251876Speter } 989251876Speter 990251876Speter return; 991251876Speter} 992251876Speter 993251876Speterstatic int outputParams(apr_dbd_t *sql, apr_dbd_prepared_t *stmt) 994251876Speter{ 995251876Speter OCIParam *parms; 996251876Speter int i; 997251876Speter ub2 paramtype[DBD_ORACLE_MAX_COLUMNS]; 998251876Speter ub2 paramsize[DBD_ORACLE_MAX_COLUMNS]; 999251876Speter char *paramname[DBD_ORACLE_MAX_COLUMNS]; 1000251876Speter ub4 paramnamelen[DBD_ORACLE_MAX_COLUMNS]; 1001251876Speter int_errorcode; 1002251876Speter 1003251876Speter /* Perl uses 0 where we used 1 */ 1004251876Speter sql->status = OCIStmtExecute(sql->svc, stmt->stmt, sql->err, 0, 0, 1005251876Speter NULL, NULL, OCI_DESCRIBE_ONLY); 1006251876Speter switch (sql->status) { 1007251876Speter case OCI_SUCCESS: 1008251876Speter case OCI_SUCCESS_WITH_INFO: 1009251876Speter break; 1010251876Speter case OCI_ERROR: 1011251876Speter#ifdef DEBUG 1012251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1013251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1014251876Speter printf("Describing prepared statement: %s\n", sql->buf); 1015251876Speter#endif 1016251876Speter default: 1017251876Speter return 1; 1018251876Speter } 1019251876Speter while (sql->status == OCI_SUCCESS) { 1020251876Speter sql->status = OCIParamGet(stmt->stmt, OCI_HTYPE_STMT, 1021251876Speter sql->err, (dvoid**)&parms, stmt->nout+1); 1022251876Speter switch (sql->status) { 1023251876Speter case OCI_SUCCESS: 1024251876Speter sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM, 1025251876Speter ¶mtype[stmt->nout], 1026251876Speter 0, OCI_ATTR_DATA_TYPE, sql->err); 1027251876Speter sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM, 1028251876Speter ¶msize[stmt->nout], 1029251876Speter 0, OCI_ATTR_DATA_SIZE, sql->err); 1030251876Speter sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM, 1031251876Speter ¶mname[stmt->nout], 1032251876Speter ¶mnamelen[stmt->nout], 1033251876Speter OCI_ATTR_NAME, sql->err); 1034251876Speter ++stmt->nout; 1035251876Speter } 1036251876Speter } 1037251876Speter switch (sql->status) { 1038251876Speter case OCI_SUCCESS: 1039251876Speter break; 1040251876Speter case OCI_ERROR: 1041251876Speter break; /* this is what we expect at end-of-loop */ 1042251876Speter default: 1043251876Speter return 1; 1044251876Speter } 1045251876Speter 1046251876Speter /* OK, the above works. We have the params; now OCIDefine them */ 1047251876Speter stmt->out = apr_palloc(stmt->pool, stmt->nout*sizeof(define_arg)); 1048251876Speter for (i=0; i<stmt->nout; ++i) { 1049251876Speter stmt->out[i].type = paramtype[i]; 1050251876Speter stmt->out[i].len = stmt->out[i].sz = paramsize[i]; 1051251876Speter stmt->out[i].name = apr_pstrmemdup(stmt->pool, 1052251876Speter paramname[i], paramnamelen[i]); 1053251876Speter switch (stmt->out[i].type) { 1054251876Speter default: 1055251876Speter switch (stmt->out[i].type) { 1056251876Speter case SQLT_NUM: /* 2: numeric, Perl worst case=130+38+3 */ 1057251876Speter stmt->out[i].sz = 171; 1058251876Speter break; 1059251876Speter case SQLT_CHR: /* 1: char */ 1060251876Speter case SQLT_AFC: /* 96: ANSI fixed char */ 1061251876Speter stmt->out[i].sz *= 4; /* ugh, wasteful UCS-4 handling */ 1062251876Speter break; 1063251876Speter case SQLT_DAT: /* 12: date, depends on NLS date format */ 1064251876Speter stmt->out[i].sz = 75; 1065251876Speter break; 1066251876Speter case SQLT_BIN: /* 23: raw binary, perhaps UTF-16? */ 1067251876Speter stmt->out[i].sz *= 2; 1068251876Speter break; 1069251876Speter case SQLT_RID: /* 11: rowid */ 1070251876Speter case SQLT_RDD: /* 104: rowid descriptor */ 1071251876Speter stmt->out[i].sz = 20; 1072251876Speter break; 1073251876Speter case SQLT_TIMESTAMP: /* 187: timestamp */ 1074251876Speter case SQLT_TIMESTAMP_TZ: /* 188: timestamp with time zone */ 1075251876Speter case SQLT_INTERVAL_YM: /* 189: interval year-to-month */ 1076251876Speter case SQLT_INTERVAL_DS: /* 190: interval day-to-second */ 1077251876Speter case SQLT_TIMESTAMP_LTZ: /* 232: timestamp with local time zone */ 1078251876Speter stmt->out[i].sz = 75; 1079251876Speter break; 1080251876Speter default: 1081251876Speter#ifdef DEBUG 1082251876Speter printf("Unsupported data type: %d\n", stmt->out[i].type); 1083251876Speter#endif 1084251876Speter break; 1085251876Speter } 1086251876Speter ++stmt->out[i].sz; 1087251876Speter stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz); 1088251876Speter sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, 1089251876Speter sql->err, i+1, 1090251876Speter stmt->out[i].buf.sval, 1091251876Speter stmt->out[i].sz, SQLT_STR, 1092251876Speter &stmt->out[i].ind, &stmt->out[i].len, 1093251876Speter 0, OCI_DEFAULT); 1094251876Speter break; 1095251876Speter case SQLT_LNG: /* 8: long */ 1096251876Speter stmt->out[i].sz = sql->long_size * 4 + 4; /* ugh, UCS-4 handling */ 1097251876Speter stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz); 1098251876Speter sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, 1099251876Speter sql->err, i+1, 1100251876Speter stmt->out[i].buf.raw, 1101251876Speter stmt->out[i].sz, SQLT_LVC, 1102251876Speter &stmt->out[i].ind, NULL, 1103251876Speter 0, OCI_DEFAULT); 1104251876Speter break; 1105251876Speter case SQLT_LBI: /* 24: long binary, perhaps UTF-16? */ 1106251876Speter stmt->out[i].sz = sql->long_size * 2 + 4; /* room for int prefix */ 1107251876Speter stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz); 1108251876Speter sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, 1109251876Speter sql->err, i+1, 1110251876Speter stmt->out[i].buf.raw, 1111251876Speter stmt->out[i].sz, SQLT_LVB, 1112251876Speter &stmt->out[i].ind, NULL, 1113251876Speter 0, OCI_DEFAULT); 1114251876Speter break; 1115251876Speter case SQLT_BLOB: /* 113 */ 1116251876Speter case SQLT_CLOB: /* 112 */ 1117251876Speter/*http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96584/oci05bnd.htm#434937*/ 1118251876Speter sql->status = OCIDescriptorAlloc(dbd_oracle_env, 1119251876Speter (dvoid**)&stmt->out[i].buf.lobval, 1120251876Speter OCI_DTYPE_LOB, 0, NULL); 1121251876Speter apr_pool_cleanup_register(stmt->pool, stmt->out[i].buf.lobval, 1122251876Speter dbd_free_lobdesc, 1123251876Speter apr_pool_cleanup_null); 1124251876Speter sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, 1125251876Speter sql->err, i+1, 1126251876Speter (dvoid*) &stmt->out[i].buf.lobval, 1127251876Speter -1, stmt->out[i].type, 1128251876Speter &stmt->out[i].ind, &stmt->out[i].len, 1129251876Speter 0, OCI_DEFAULT); 1130251876Speter break; 1131251876Speter } 1132251876Speter switch (sql->status) { 1133251876Speter case OCI_SUCCESS: 1134251876Speter break; 1135251876Speter default: 1136251876Speter return 1; 1137251876Speter } 1138251876Speter } 1139251876Speter return 0; 1140251876Speter} 1141251876Speter 1142251876Speterstatic int dbd_oracle_pquery(apr_pool_t *pool, apr_dbd_t *sql, 1143251876Speter int *nrows, apr_dbd_prepared_t *statement, 1144251876Speter const char **values) 1145251876Speter{ 1146251876Speter OCISnapshot *oldsnapshot = NULL; 1147251876Speter OCISnapshot *newsnapshot = NULL; 1148251876Speter apr_dbd_transaction_t* trans = sql->trans; 1149251876Speter int exec_mode; 1150251876Speter int_errorcode; 1151251876Speter 1152251876Speter if (trans) { 1153251876Speter switch (trans->status) { 1154251876Speter case TRANS_ERROR: 1155251876Speter return -1; 1156251876Speter case TRANS_NONE: 1157251876Speter trans = NULL; 1158251876Speter break; 1159251876Speter case TRANS_1: 1160251876Speter oldsnapshot = trans->snapshot1; 1161251876Speter newsnapshot = trans->snapshot2; 1162251876Speter trans->status = TRANS_2; 1163251876Speter break; 1164251876Speter case TRANS_2: 1165251876Speter oldsnapshot = trans->snapshot2; 1166251876Speter newsnapshot = trans->snapshot1; 1167251876Speter trans->status = TRANS_1; 1168251876Speter break; 1169251876Speter } 1170251876Speter exec_mode = OCI_DEFAULT; 1171251876Speter } 1172251876Speter else { 1173251876Speter exec_mode = OCI_COMMIT_ON_SUCCESS; 1174251876Speter } 1175251876Speter 1176251876Speter dbd_oracle_bind(statement, values); 1177251876Speter 1178251876Speter sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 1, 0, 1179251876Speter oldsnapshot, newsnapshot, exec_mode); 1180251876Speter switch (sql->status) { 1181251876Speter case OCI_SUCCESS: 1182251876Speter break; 1183251876Speter case OCI_ERROR: 1184251876Speter#ifdef DEBUG 1185251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1186251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1187251876Speter printf("Execute error %d: %s\n", sql->status, sql->buf); 1188251876Speter#endif 1189251876Speter /* fallthrough */ 1190251876Speter default: 1191251876Speter if (TXN_NOTICE_ERRORS(trans)) { 1192251876Speter trans->status = TRANS_ERROR; 1193251876Speter } 1194251876Speter return 1; 1195251876Speter } 1196251876Speter 1197251876Speter sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT, nrows, 0, 1198251876Speter OCI_ATTR_ROW_COUNT, sql->err); 1199251876Speter return 0; 1200251876Speter} 1201251876Speter 1202251876Speterstatic int dbd_oracle_pvquery(apr_pool_t *pool, apr_dbd_t *sql, 1203251876Speter int *nrows, apr_dbd_prepared_t *statement, 1204251876Speter va_list args) 1205251876Speter{ 1206251876Speter const char **values; 1207251876Speter int i; 1208251876Speter 1209251876Speter if (sql->trans && sql->trans->status == TRANS_ERROR) { 1210251876Speter return -1; 1211251876Speter } 1212251876Speter 1213251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 1214251876Speter 1215251876Speter for (i = 0; i < statement->nvals; i++) { 1216251876Speter values[i] = va_arg(args, const char*); 1217251876Speter } 1218251876Speter 1219251876Speter return dbd_oracle_pquery(pool, sql, nrows, statement, values); 1220251876Speter} 1221251876Speter 1222251876Speterstatic int dbd_oracle_pselect(apr_pool_t *pool, apr_dbd_t *sql, 1223251876Speter apr_dbd_results_t **results, 1224251876Speter apr_dbd_prepared_t *statement, 1225251876Speter int seek, const char **values) 1226251876Speter{ 1227251876Speter int exec_mode = seek ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT; 1228251876Speter OCISnapshot *oldsnapshot = NULL; 1229251876Speter OCISnapshot *newsnapshot = NULL; 1230251876Speter apr_dbd_transaction_t* trans = sql->trans; 1231251876Speter int_errorcode; 1232251876Speter 1233251876Speter if (trans) { 1234251876Speter switch (trans->status) { 1235251876Speter case TRANS_ERROR: 1236251876Speter return 1; 1237251876Speter case TRANS_NONE: 1238251876Speter trans = NULL; 1239251876Speter break; 1240251876Speter case TRANS_1: 1241251876Speter oldsnapshot = trans->snapshot1; 1242251876Speter newsnapshot = trans->snapshot2; 1243251876Speter trans->status = TRANS_2; 1244251876Speter break; 1245251876Speter case TRANS_2: 1246251876Speter oldsnapshot = trans->snapshot2; 1247251876Speter newsnapshot = trans->snapshot1; 1248251876Speter trans->status = TRANS_1; 1249251876Speter break; 1250251876Speter } 1251251876Speter } 1252251876Speter 1253251876Speter dbd_oracle_bind(statement, values); 1254251876Speter 1255251876Speter sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 0, 0, 1256251876Speter oldsnapshot, newsnapshot, exec_mode); 1257251876Speter switch (sql->status) { 1258251876Speter case OCI_SUCCESS: 1259251876Speter break; 1260251876Speter case OCI_ERROR: 1261251876Speter#ifdef DEBUG 1262251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1263251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1264251876Speter printf("Executing prepared statement: %s\n", sql->buf); 1265251876Speter#endif 1266251876Speter /* fallthrough */ 1267251876Speter default: 1268251876Speter if (TXN_NOTICE_ERRORS(trans)) { 1269251876Speter trans->status = TRANS_ERROR; 1270251876Speter } 1271251876Speter return 1; 1272251876Speter } 1273251876Speter 1274251876Speter if (!*results) { 1275251876Speter *results = apr_palloc(pool, sizeof(apr_dbd_results_t)); 1276251876Speter } 1277251876Speter (*results)->handle = sql; 1278251876Speter (*results)->statement = statement; 1279251876Speter (*results)->seek = seek; 1280251876Speter (*results)->rownum = seek ? 0 : -1; 1281251876Speter (*results)->pool = pool; 1282251876Speter 1283251876Speter return 0; 1284251876Speter} 1285251876Speter 1286251876Speterstatic int dbd_oracle_pvselect(apr_pool_t *pool, apr_dbd_t *sql, 1287251876Speter apr_dbd_results_t **results, 1288251876Speter apr_dbd_prepared_t *statement, 1289251876Speter int seek, va_list args) 1290251876Speter{ 1291251876Speter const char **values; 1292251876Speter int i; 1293251876Speter 1294251876Speter if (sql->trans && sql->trans->status == TRANS_ERROR) { 1295251876Speter return -1; 1296251876Speter } 1297251876Speter 1298251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 1299251876Speter 1300251876Speter for (i = 0; i < statement->nvals; i++) { 1301251876Speter values[i] = va_arg(args, const char*); 1302251876Speter } 1303251876Speter 1304251876Speter return dbd_oracle_pselect(pool, sql, results, statement, seek, values); 1305251876Speter} 1306251876Speter 1307251876Speterstatic void dbd_oracle_bbind(apr_dbd_prepared_t * statement, 1308251876Speter const void **values) 1309251876Speter{ 1310251876Speter OCIStmt *stmt = statement->stmt; 1311251876Speter apr_dbd_t *sql = statement->handle; 1312251876Speter int i, j; 1313251876Speter sb2 null_ind = -1; 1314251876Speter apr_dbd_type_e type; 1315251876Speter 1316251876Speter for (i = 0, j = 0; i < statement->nargs; i++, j++) { 1317251876Speter type = (values[j] == NULL ? APR_DBD_TYPE_NULL 1318251876Speter : statement->args[i].type); 1319251876Speter 1320251876Speter switch (type) { 1321251876Speter case APR_DBD_TYPE_TINY: 1322251876Speter statement->args[i].value.ival = *(char*)values[j]; 1323251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1324251876Speter sql->err, i + 1, 1325251876Speter &statement->args[i].value.ival, 1326251876Speter sizeof(statement->args[i].value.ival), 1327251876Speter SQLT_INT, 1328251876Speter &statement->args[i].ind, NULL, 1329251876Speter (ub2) 0, (ub4) 0, 1330251876Speter (ub4 *) 0, OCI_DEFAULT); 1331251876Speter break; 1332251876Speter case APR_DBD_TYPE_UTINY: 1333251876Speter statement->args[i].value.uval = *(unsigned char*)values[j]; 1334251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1335251876Speter sql->err, i + 1, 1336251876Speter &statement->args[i].value.uval, 1337251876Speter sizeof(statement->args[i].value.uval), 1338251876Speter SQLT_UIN, 1339251876Speter &statement->args[i].ind, NULL, 1340251876Speter (ub2) 0, (ub4) 0, 1341251876Speter (ub4 *) 0, OCI_DEFAULT); 1342251876Speter break; 1343251876Speter case APR_DBD_TYPE_SHORT: 1344251876Speter statement->args[i].value.ival = *(short*)values[j]; 1345251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1346251876Speter sql->err, i + 1, 1347251876Speter &statement->args[i].value.ival, 1348251876Speter sizeof(statement->args[i].value.ival), 1349251876Speter SQLT_INT, 1350251876Speter &statement->args[i].ind, NULL, 1351251876Speter (ub2) 0, (ub4) 0, 1352251876Speter (ub4 *) 0, OCI_DEFAULT); 1353251876Speter break; 1354251876Speter case APR_DBD_TYPE_USHORT: 1355251876Speter statement->args[i].value.uval = *(unsigned short*)values[j]; 1356251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1357251876Speter sql->err, i + 1, 1358251876Speter &statement->args[i].value.uval, 1359251876Speter sizeof(statement->args[i].value.uval), 1360251876Speter SQLT_UIN, 1361251876Speter &statement->args[i].ind, NULL, 1362251876Speter (ub2) 0, (ub4) 0, 1363251876Speter (ub4 *) 0, OCI_DEFAULT); 1364251876Speter break; 1365251876Speter case APR_DBD_TYPE_INT: 1366251876Speter statement->args[i].value.ival = *(int*)values[j]; 1367251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1368251876Speter sql->err, i + 1, 1369251876Speter &statement->args[i].value.ival, 1370251876Speter sizeof(statement->args[i].value.ival), 1371251876Speter SQLT_INT, 1372251876Speter &statement->args[i].ind, NULL, 1373251876Speter (ub2) 0, (ub4) 0, 1374251876Speter (ub4 *) 0, OCI_DEFAULT); 1375251876Speter break; 1376251876Speter case APR_DBD_TYPE_UINT: 1377251876Speter statement->args[i].value.uval = *(unsigned int*)values[j]; 1378251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1379251876Speter sql->err, i + 1, 1380251876Speter &statement->args[i].value.uval, 1381251876Speter sizeof(statement->args[i].value.uval), 1382251876Speter SQLT_UIN, 1383251876Speter &statement->args[i].ind, NULL, 1384251876Speter (ub2) 0, (ub4) 0, 1385251876Speter (ub4 *) 0, OCI_DEFAULT); 1386251876Speter break; 1387251876Speter case APR_DBD_TYPE_LONG: 1388251876Speter statement->args[i].value.sval = 1389251876Speter apr_psprintf(statement->pool, "%ld", *(long*)values[j]); 1390251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1391251876Speter sql->err, i + 1, 1392251876Speter statement->args[i].value.sval, 1393251876Speter strlen(statement->args[i].value.sval)+1, 1394251876Speter SQLT_STR, 1395251876Speter &statement->args[i].ind, NULL, 1396251876Speter (ub2) 0, (ub4) 0, 1397251876Speter (ub4 *) 0, OCI_DEFAULT); 1398251876Speter break; 1399251876Speter case APR_DBD_TYPE_ULONG: 1400251876Speter statement->args[i].value.sval = 1401251876Speter apr_psprintf(statement->pool, "%lu", 1402251876Speter *(unsigned long*)values[j]); 1403251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1404251876Speter sql->err, i + 1, 1405251876Speter statement->args[i].value.sval, 1406251876Speter strlen(statement->args[i].value.sval)+1, 1407251876Speter SQLT_STR, 1408251876Speter &statement->args[i].ind, NULL, 1409251876Speter (ub2) 0, (ub4) 0, 1410251876Speter (ub4 *) 0, OCI_DEFAULT); 1411251876Speter break; 1412251876Speter case APR_DBD_TYPE_LONGLONG: 1413251876Speter statement->args[i].value.sval = 1414251876Speter apr_psprintf(statement->pool, "%" APR_INT64_T_FMT, 1415251876Speter *(apr_int64_t*)values[j]); 1416251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1417251876Speter sql->err, i + 1, 1418251876Speter statement->args[i].value.sval, 1419251876Speter strlen(statement->args[i].value.sval)+1, 1420251876Speter SQLT_STR, 1421251876Speter &statement->args[i].ind, NULL, 1422251876Speter (ub2) 0, (ub4) 0, 1423251876Speter (ub4 *) 0, OCI_DEFAULT); 1424251876Speter break; 1425251876Speter case APR_DBD_TYPE_ULONGLONG: 1426251876Speter statement->args[i].value.sval = 1427251876Speter apr_psprintf(statement->pool, "%" APR_UINT64_T_FMT, 1428251876Speter *(apr_uint64_t*)values[j]); 1429251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1430251876Speter sql->err, i + 1, 1431251876Speter statement->args[i].value.sval, 1432251876Speter strlen(statement->args[i].value.sval)+1, 1433251876Speter SQLT_UIN, 1434251876Speter &statement->args[i].ind, NULL, 1435251876Speter (ub2) 0, (ub4) 0, 1436251876Speter (ub4 *) 0, OCI_DEFAULT); 1437251876Speter break; 1438251876Speter case APR_DBD_TYPE_FLOAT: 1439251876Speter statement->args[i].value.fval = *(float*)values[j]; 1440251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1441251876Speter sql->err, i + 1, 1442251876Speter &statement->args[i].value.fval, 1443251876Speter sizeof(statement->args[i].value.fval), 1444251876Speter SQLT_FLT, 1445251876Speter &statement->args[i].ind, NULL, 1446251876Speter (ub2) 0, (ub4) 0, 1447251876Speter (ub4 *) 0, OCI_DEFAULT); 1448251876Speter break; 1449251876Speter case APR_DBD_TYPE_DOUBLE: 1450251876Speter statement->args[i].value.fval = *(double*)values[j]; 1451251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1452251876Speter sql->err, i + 1, 1453251876Speter &statement->args[i].value.fval, 1454251876Speter sizeof(statement->args[i].value.fval), 1455251876Speter SQLT_FLT, 1456251876Speter &statement->args[i].ind, NULL, 1457251876Speter (ub2) 0, (ub4) 0, 1458251876Speter (ub4 *) 0, OCI_DEFAULT); 1459251876Speter break; 1460251876Speter case APR_DBD_TYPE_STRING: 1461251876Speter case APR_DBD_TYPE_TEXT: 1462251876Speter case APR_DBD_TYPE_TIME: 1463251876Speter case APR_DBD_TYPE_DATE: 1464251876Speter case APR_DBD_TYPE_DATETIME: 1465251876Speter case APR_DBD_TYPE_TIMESTAMP: 1466251876Speter case APR_DBD_TYPE_ZTIMESTAMP: 1467251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1468251876Speter sql->err, i + 1, 1469251876Speter (dvoid*) values[j], 1470251876Speter strlen(values[j]) + 1, 1471251876Speter SQLT_STR, 1472251876Speter &statement->args[i].ind, NULL, 1473251876Speter (ub2) 0, (ub4) 0, 1474251876Speter (ub4 *) 0, OCI_DEFAULT); 1475251876Speter break; 1476251876Speter case APR_DBD_TYPE_BLOB: 1477251876Speter { 1478251876Speter char *data = (char *)values[j]; 1479251876Speter apr_size_t size = *(apr_size_t*)values[++j]; 1480251876Speter 1481251876Speter /* skip table and column for now */ 1482251876Speter j += 2; 1483251876Speter 1484251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1485251876Speter sql->err, i + 1, 1486251876Speter data, size, SQLT_LBI, 1487251876Speter &statement->args[i].ind, 1488251876Speter NULL, 1489251876Speter (ub2) 0, (ub4) 0, 1490251876Speter (ub4 *) 0, OCI_DEFAULT); 1491251876Speter } 1492251876Speter break; 1493251876Speter case APR_DBD_TYPE_CLOB: 1494251876Speter { 1495251876Speter char *data = (char *)values[j]; 1496251876Speter apr_size_t size = *(apr_size_t*)values[++j]; 1497251876Speter 1498251876Speter /* skip table and column for now */ 1499251876Speter j += 2; 1500251876Speter 1501251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1502251876Speter sql->err, i + 1, 1503251876Speter data, size, SQLT_LNG, 1504251876Speter &statement->args[i].ind, 1505251876Speter NULL, 1506251876Speter (ub2) 0, (ub4) 0, 1507251876Speter (ub4 *) 0, OCI_DEFAULT); 1508251876Speter } 1509251876Speter break; 1510251876Speter case APR_DBD_TYPE_NULL: 1511251876Speter default: 1512251876Speter sql->status = OCIBindByPos(stmt, &statement->args[i].bind, 1513251876Speter sql->err, i + 1, 1514251876Speter NULL, 0, SQLT_STR, 1515251876Speter &null_ind, NULL, 1516251876Speter (ub2) 0, (ub4) 0, 1517251876Speter (ub4 *) 0, OCI_DEFAULT); 1518251876Speter break; 1519251876Speter } 1520251876Speter 1521251876Speter if (sql->status != OCI_SUCCESS) { 1522251876Speter return; 1523251876Speter } 1524251876Speter } 1525251876Speter 1526251876Speter return; 1527251876Speter} 1528251876Speter 1529251876Speterstatic int dbd_oracle_pbquery(apr_pool_t * pool, apr_dbd_t * sql, 1530251876Speter int *nrows, apr_dbd_prepared_t * statement, 1531251876Speter const void **values) 1532251876Speter{ 1533251876Speter OCISnapshot *oldsnapshot = NULL; 1534251876Speter OCISnapshot *newsnapshot = NULL; 1535251876Speter apr_dbd_transaction_t* trans = sql->trans; 1536251876Speter int exec_mode; 1537251876Speter int_errorcode; 1538251876Speter 1539251876Speter if (trans) { 1540251876Speter switch (trans->status) { 1541251876Speter case TRANS_ERROR: 1542251876Speter return -1; 1543251876Speter case TRANS_NONE: 1544251876Speter trans = NULL; 1545251876Speter break; 1546251876Speter case TRANS_1: 1547251876Speter oldsnapshot = trans->snapshot1; 1548251876Speter newsnapshot = trans->snapshot2; 1549251876Speter trans->status = TRANS_2; 1550251876Speter break; 1551251876Speter case TRANS_2: 1552251876Speter oldsnapshot = trans->snapshot2; 1553251876Speter newsnapshot = trans->snapshot1; 1554251876Speter trans->status = TRANS_1; 1555251876Speter break; 1556251876Speter } 1557251876Speter exec_mode = OCI_DEFAULT; 1558251876Speter } 1559251876Speter else { 1560251876Speter exec_mode = OCI_COMMIT_ON_SUCCESS; 1561251876Speter } 1562251876Speter 1563251876Speter dbd_oracle_bbind(statement, values); 1564251876Speter 1565251876Speter sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 1, 0, 1566251876Speter oldsnapshot, newsnapshot, exec_mode); 1567251876Speter switch (sql->status) { 1568251876Speter case OCI_SUCCESS: 1569251876Speter break; 1570251876Speter case OCI_ERROR: 1571251876Speter#ifdef DEBUG 1572251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1573251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1574251876Speter printf("Execute error %d: %s\n", sql->status, sql->buf); 1575251876Speter#endif 1576251876Speter /* fallthrough */ 1577251876Speter default: 1578251876Speter if (TXN_NOTICE_ERRORS(trans)) { 1579251876Speter trans->status = TRANS_ERROR; 1580251876Speter } 1581251876Speter return 1; 1582251876Speter } 1583251876Speter 1584251876Speter sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT, nrows, 0, 1585251876Speter OCI_ATTR_ROW_COUNT, sql->err); 1586251876Speter return 0; 1587251876Speter} 1588251876Speter 1589251876Speterstatic int dbd_oracle_pvbquery(apr_pool_t * pool, apr_dbd_t * sql, 1590251876Speter int *nrows, apr_dbd_prepared_t * statement, 1591251876Speter va_list args) 1592251876Speter{ 1593251876Speter const void **values; 1594251876Speter int i; 1595251876Speter 1596251876Speter if (sql->trans && sql->trans->status == TRANS_ERROR) { 1597251876Speter return -1; 1598251876Speter } 1599251876Speter 1600251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 1601251876Speter 1602251876Speter for (i = 0; i < statement->nvals; i++) { 1603251876Speter values[i] = va_arg(args, const void*); 1604251876Speter } 1605251876Speter 1606251876Speter return dbd_oracle_pbquery(pool, sql, nrows, statement, values); 1607251876Speter} 1608251876Speter 1609251876Speterstatic int dbd_oracle_pbselect(apr_pool_t * pool, apr_dbd_t * sql, 1610251876Speter apr_dbd_results_t ** results, 1611251876Speter apr_dbd_prepared_t * statement, 1612251876Speter int seek, const void **values) 1613251876Speter{ 1614251876Speter int exec_mode = seek ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT; 1615251876Speter OCISnapshot *oldsnapshot = NULL; 1616251876Speter OCISnapshot *newsnapshot = NULL; 1617251876Speter apr_dbd_transaction_t* trans = sql->trans; 1618251876Speter int_errorcode; 1619251876Speter 1620251876Speter if (trans) { 1621251876Speter switch (trans->status) { 1622251876Speter case TRANS_ERROR: 1623251876Speter return 1; 1624251876Speter case TRANS_NONE: 1625251876Speter trans = NULL; 1626251876Speter break; 1627251876Speter case TRANS_1: 1628251876Speter oldsnapshot = trans->snapshot1; 1629251876Speter newsnapshot = trans->snapshot2; 1630251876Speter trans->status = TRANS_2; 1631251876Speter break; 1632251876Speter case TRANS_2: 1633251876Speter oldsnapshot = trans->snapshot2; 1634251876Speter newsnapshot = trans->snapshot1; 1635251876Speter trans->status = TRANS_1; 1636251876Speter break; 1637251876Speter } 1638251876Speter } 1639251876Speter 1640251876Speter dbd_oracle_bbind(statement, values); 1641251876Speter 1642251876Speter sql->status = OCIStmtExecute(sql->svc, statement->stmt, sql->err, 0, 0, 1643251876Speter oldsnapshot, newsnapshot, exec_mode); 1644251876Speter switch (sql->status) { 1645251876Speter case OCI_SUCCESS: 1646251876Speter break; 1647251876Speter case OCI_ERROR: 1648251876Speter#ifdef DEBUG 1649251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1650251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1651251876Speter printf("Executing prepared statement: %s\n", sql->buf); 1652251876Speter#endif 1653251876Speter /* fallthrough */ 1654251876Speter default: 1655251876Speter if (TXN_NOTICE_ERRORS(trans)) { 1656251876Speter trans->status = TRANS_ERROR; 1657251876Speter } 1658251876Speter return 1; 1659251876Speter } 1660251876Speter 1661251876Speter if (!*results) { 1662251876Speter *results = apr_palloc(pool, sizeof(apr_dbd_results_t)); 1663251876Speter } 1664251876Speter (*results)->handle = sql; 1665251876Speter (*results)->statement = statement; 1666251876Speter (*results)->seek = seek; 1667251876Speter (*results)->rownum = seek ? 0 : -1; 1668251876Speter (*results)->pool = pool; 1669251876Speter 1670251876Speter return 0; 1671251876Speter} 1672251876Speter 1673251876Speterstatic int dbd_oracle_pvbselect(apr_pool_t * pool, apr_dbd_t * sql, 1674251876Speter apr_dbd_results_t ** results, 1675251876Speter apr_dbd_prepared_t * statement, int seek, 1676251876Speter va_list args) 1677251876Speter{ 1678251876Speter const void **values; 1679251876Speter int i; 1680251876Speter 1681251876Speter if (sql->trans && sql->trans->status == TRANS_ERROR) { 1682251876Speter return -1; 1683251876Speter } 1684251876Speter 1685251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 1686251876Speter 1687251876Speter for (i = 0; i < statement->nvals; i++) { 1688251876Speter values[i] = va_arg(args, const void*); 1689251876Speter } 1690251876Speter 1691251876Speter return dbd_oracle_pbselect(pool, sql, results, statement, seek, values); 1692251876Speter} 1693251876Speter 1694251876Speterstatic int dbd_oracle_start_transaction(apr_pool_t *pool, apr_dbd_t *sql, 1695251876Speter apr_dbd_transaction_t **trans) 1696251876Speter{ 1697251876Speter int ret = 0; 1698251876Speter int_errorcode; 1699251876Speter if (*trans) { 1700251876Speter dbd_oracle_end_transaction(*trans); 1701251876Speter } 1702251876Speter else { 1703251876Speter *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t)); 1704251876Speter OCIHandleAlloc(dbd_oracle_env, (dvoid**)&(*trans)->trans, 1705251876Speter OCI_HTYPE_TRANS, 0, 0); 1706251876Speter OCIAttrSet(sql->svc, OCI_HTYPE_SVCCTX, (*trans)->trans, 0, 1707251876Speter OCI_ATTR_TRANS, sql->err); 1708251876Speter } 1709251876Speter 1710251876Speter 1711251876Speter sql->status = OCITransStart(sql->svc, sql->err, TRANS_TIMEOUT, 1712251876Speter OCI_TRANS_NEW); 1713251876Speter switch (sql->status) { 1714251876Speter case OCI_ERROR: 1715251876Speter#ifdef DEBUG 1716251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, sql->buf, 1717251876Speter sizeof(sql->buf), OCI_HTYPE_ERROR); 1718251876Speter printf("Transaction: %s\n", sql->buf); 1719251876Speter#endif 1720251876Speter ret = 1; 1721251876Speter break; 1722251876Speter case OCI_SUCCESS: 1723251876Speter (*trans)->handle = sql; 1724251876Speter (*trans)->status = TRANS_1; 1725251876Speter sql->trans = *trans; 1726251876Speter switch (OCIDescriptorAlloc(dbd_oracle_env, 1727251876Speter (dvoid**)&(*trans)->snapshot1, 1728251876Speter OCI_DTYPE_SNAP, 0, NULL)) { 1729251876Speter case OCI_SUCCESS: 1730251876Speter apr_pool_cleanup_register(pool, (*trans)->snapshot1, 1731251876Speter dbd_free_snapshot, apr_pool_cleanup_null); 1732251876Speter break; 1733251876Speter case OCI_INVALID_HANDLE: 1734251876Speter ret = 1; 1735251876Speter break; 1736251876Speter } 1737251876Speter switch (OCIDescriptorAlloc(dbd_oracle_env, 1738251876Speter (dvoid**)&(*trans)->snapshot2, 1739251876Speter OCI_DTYPE_SNAP, 0, NULL)) { 1740251876Speter case OCI_SUCCESS: 1741251876Speter apr_pool_cleanup_register(pool, (*trans)->snapshot2, 1742251876Speter dbd_free_snapshot, apr_pool_cleanup_null); 1743251876Speter break; 1744251876Speter case OCI_INVALID_HANDLE: 1745251876Speter ret = 1; 1746251876Speter break; 1747251876Speter } 1748251876Speter break; 1749251876Speter default: 1750251876Speter ret = 1; 1751251876Speter break; 1752251876Speter } 1753251876Speter return ret; 1754251876Speter} 1755251876Speter 1756251876Speterstatic int dbd_oracle_end_transaction(apr_dbd_transaction_t *trans) 1757251876Speter{ 1758251876Speter int ret = 1; /* no transaction is an error cond */ 1759251876Speter sword status; 1760251876Speter apr_dbd_t *handle = trans->handle; 1761251876Speter if (trans) { 1762251876Speter switch (trans->status) { 1763251876Speter case TRANS_NONE: /* No trans is an error here */ 1764251876Speter status = OCI_ERROR; 1765251876Speter break; 1766251876Speter case TRANS_ERROR: 1767251876Speter status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT); 1768251876Speter break; 1769251876Speter default: 1770251876Speter /* rollback on explicit rollback request */ 1771251876Speter if (TXN_DO_ROLLBACK(trans)) { 1772251876Speter status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT); 1773251876Speter } else { 1774251876Speter status = OCITransCommit(handle->svc, handle->err, OCI_DEFAULT); 1775251876Speter } 1776251876Speter break; 1777251876Speter } 1778251876Speter 1779251876Speter handle->trans = NULL; 1780251876Speter 1781251876Speter switch (status) { 1782251876Speter case OCI_SUCCESS: 1783251876Speter ret = 0; 1784251876Speter break; 1785251876Speter default: 1786251876Speter ret = 3; 1787251876Speter break; 1788251876Speter } 1789251876Speter } 1790251876Speter return ret; 1791251876Speter} 1792251876Speter 1793251876Speterstatic int dbd_oracle_transaction_mode_get(apr_dbd_transaction_t *trans) 1794251876Speter{ 1795251876Speter if (!trans) 1796251876Speter return APR_DBD_TRANSACTION_COMMIT; 1797251876Speter 1798251876Speter return trans->mode; 1799251876Speter} 1800251876Speter 1801251876Speterstatic int dbd_oracle_transaction_mode_set(apr_dbd_transaction_t *trans, 1802251876Speter int mode) 1803251876Speter{ 1804251876Speter if (!trans) 1805251876Speter return APR_DBD_TRANSACTION_COMMIT; 1806251876Speter 1807251876Speter return trans->mode = (mode & TXN_MODE_BITS); 1808251876Speter} 1809251876Speter 1810251876Speter/* This doesn't work for BLOB because of NULLs, but it can fake it 1811251876Speter * if the BLOB is really a string 1812251876Speter */ 1813251876Speterstatic const char *dbd_oracle_get_entry(const apr_dbd_row_t *row, int n) 1814251876Speter{ 1815251876Speter ub4 len = 0; 1816251876Speter ub1 csform = 0; 1817251876Speter ub2 csid = 0; 1818251876Speter apr_size_t buflen = 0; 1819251876Speter char *buf = NULL; 1820251876Speter define_arg *val = &row->res->statement->out[n]; 1821251876Speter apr_dbd_t *sql = row->res->handle; 1822251876Speter int_errorcode; 1823251876Speter 1824251876Speter if ((n < 0) || (n >= row->res->statement->nout) || (val->ind == -1)) { 1825251876Speter return NULL; 1826251876Speter } 1827251876Speter 1828251876Speter switch (val->type) { 1829251876Speter case SQLT_BLOB: 1830251876Speter case SQLT_CLOB: 1831251876Speter sql->status = OCILobGetLength(sql->svc, sql->err, val->buf.lobval, 1832251876Speter &len); 1833251876Speter switch (sql->status) { 1834251876Speter case OCI_SUCCESS: 1835251876Speter case OCI_SUCCESS_WITH_INFO: 1836251876Speter if (len == 0) { 1837251876Speter buf = ""; 1838251876Speter } 1839251876Speter break; 1840251876Speter case OCI_ERROR: 1841251876Speter#ifdef DEBUG 1842251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1843251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1844251876Speter printf("Finding LOB length: %s\n", sql->buf); 1845251876Speter break; 1846251876Speter#endif 1847251876Speter default: 1848251876Speter break; 1849251876Speter } 1850251876Speter 1851251876Speter if (len == 0) { 1852251876Speter break; 1853251876Speter } 1854251876Speter 1855251876Speter if (val->type == APR_DBD_TYPE_CLOB) { 1856251876Speter#if 1 1857251876Speter /* Is this necessary, or can it be defaulted? */ 1858251876Speter sql->status = OCILobCharSetForm(dbd_oracle_env, sql->err, 1859251876Speter val->buf.lobval, &csform); 1860251876Speter if (sql->status == OCI_SUCCESS) { 1861251876Speter sql->status = OCILobCharSetId(dbd_oracle_env, sql->err, 1862251876Speter val->buf.lobval, &csid); 1863251876Speter } 1864251876Speter switch (sql->status) { 1865251876Speter case OCI_SUCCESS: 1866251876Speter case OCI_SUCCESS_WITH_INFO: 1867251876Speter buflen = (len+1) * 4; /* ugh, wasteful UCS-4 handling */ 1868251876Speter /* zeroise all - where the string ends depends on charset */ 1869251876Speter buf = apr_pcalloc(row->pool, buflen); 1870251876Speter break; 1871251876Speter#ifdef DEBUG 1872251876Speter case OCI_ERROR: 1873251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1874251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1875251876Speter printf("Reading LOB character set: %s\n", sql->buf); 1876251876Speter break; /*** XXX?? ***/ 1877251876Speter#endif 1878251876Speter default: 1879251876Speter break; /*** XXX?? ***/ 1880251876Speter } 1881251876Speter#else /* ignore charset */ 1882251876Speter buflen = (len+1) * 4; /* ugh, wasteful UCS-4 handling */ 1883251876Speter /* zeroise all - where the string ends depends on charset */ 1884251876Speter buf = apr_pcalloc(row->pool, buflen); 1885251876Speter#endif 1886251876Speter } else { 1887251876Speter /* BUG: this'll only work if the BLOB looks like a string */ 1888251876Speter buflen = len; 1889251876Speter buf = apr_palloc(row->pool, buflen+1); 1890251876Speter buf[buflen] = 0; 1891251876Speter } 1892251876Speter 1893251876Speter if (!buf) { 1894251876Speter break; 1895251876Speter } 1896251876Speter 1897251876Speter sql->status = OCILobRead(sql->svc, sql->err, val->buf.lobval, 1898251876Speter &len, 1, (dvoid*) buf, buflen, 1899251876Speter NULL, NULL, csid, csform); 1900251876Speter switch (sql->status) { 1901251876Speter case OCI_SUCCESS: 1902251876Speter case OCI_SUCCESS_WITH_INFO: 1903251876Speter break; 1904251876Speter#ifdef DEBUG 1905251876Speter case OCI_ERROR: 1906251876Speter OCIErrorGet(sql->err, 1, NULL, &errorcode, 1907251876Speter sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); 1908251876Speter printf("Reading LOB: %s\n", sql->buf); 1909251876Speter buf = NULL; /*** XXX?? ***/ 1910251876Speter break; 1911251876Speter#endif 1912251876Speter default: 1913251876Speter buf = NULL; /*** XXX?? ***/ 1914251876Speter break; 1915251876Speter } 1916251876Speter 1917251876Speter break; 1918251876Speter case SQLT_LNG: 1919251876Speter case SQLT_LBI: 1920251876Speter /* raw is struct { ub4 len; char *buf; } */ 1921251876Speter len = *(ub4*) val->buf.raw; 1922251876Speter buf = apr_pstrndup(row->pool, val->buf.sval + sizeof(ub4), len); 1923251876Speter break; 1924251876Speter default: 1925251876Speter buf = apr_pstrndup(row->pool, val->buf.sval, val->len); 1926251876Speter break; 1927251876Speter } 1928251876Speter return (const char*) buf; 1929251876Speter} 1930251876Speter 1931251876Speter/* XXX Should this use Oracle proper API instead of calling get_entry()? */ 1932251876Speterstatic apr_status_t dbd_oracle_datum_get(const apr_dbd_row_t *row, int n, 1933251876Speter apr_dbd_type_e type, void *data) 1934251876Speter{ 1935251876Speter define_arg *val = &row->res->statement->out[n]; 1936251876Speter const char *entry; 1937251876Speter 1938251876Speter if ((n < 0) || (n >= row->res->statement->nout)) { 1939251876Speter return APR_EGENERAL; 1940251876Speter } 1941251876Speter 1942251876Speter if(val->ind == -1) { 1943251876Speter return APR_ENOENT; 1944251876Speter } 1945251876Speter 1946251876Speter switch (type) { 1947251876Speter case APR_DBD_TYPE_TINY: 1948251876Speter entry = dbd_oracle_get_entry(row, n); 1949251876Speter if (entry == NULL) { 1950251876Speter return APR_ENOENT; 1951251876Speter } 1952251876Speter *(char*)data = atoi(entry); 1953251876Speter break; 1954251876Speter case APR_DBD_TYPE_UTINY: 1955251876Speter entry = dbd_oracle_get_entry(row, n); 1956251876Speter if (entry == NULL) { 1957251876Speter return APR_ENOENT; 1958251876Speter } 1959251876Speter *(unsigned char*)data = atoi(entry); 1960251876Speter break; 1961251876Speter case APR_DBD_TYPE_SHORT: 1962251876Speter entry = dbd_oracle_get_entry(row, n); 1963251876Speter if (entry == NULL) { 1964251876Speter return APR_ENOENT; 1965251876Speter } 1966251876Speter *(short*)data = atoi(entry); 1967251876Speter break; 1968251876Speter case APR_DBD_TYPE_USHORT: 1969251876Speter entry = dbd_oracle_get_entry(row, n); 1970251876Speter if (entry == NULL) { 1971251876Speter return APR_ENOENT; 1972251876Speter } 1973251876Speter *(unsigned short*)data = atoi(entry); 1974251876Speter break; 1975251876Speter case APR_DBD_TYPE_INT: 1976251876Speter entry = dbd_oracle_get_entry(row, n); 1977251876Speter if (entry == NULL) { 1978251876Speter return APR_ENOENT; 1979251876Speter } 1980251876Speter *(int*)data = atoi(entry); 1981251876Speter break; 1982251876Speter case APR_DBD_TYPE_UINT: 1983251876Speter entry = dbd_oracle_get_entry(row, n); 1984251876Speter if (entry == NULL) { 1985251876Speter return APR_ENOENT; 1986251876Speter } 1987251876Speter *(unsigned int*)data = atoi(entry); 1988251876Speter break; 1989251876Speter case APR_DBD_TYPE_LONG: 1990251876Speter entry = dbd_oracle_get_entry(row, n); 1991251876Speter if (entry == NULL) { 1992251876Speter return APR_ENOENT; 1993251876Speter } 1994251876Speter *(long*)data = atol(entry); 1995251876Speter break; 1996251876Speter case APR_DBD_TYPE_ULONG: 1997251876Speter entry = dbd_oracle_get_entry(row, n); 1998251876Speter if (entry == NULL) { 1999251876Speter return APR_ENOENT; 2000251876Speter } 2001251876Speter *(unsigned long*)data = atol(entry); 2002251876Speter break; 2003251876Speter case APR_DBD_TYPE_LONGLONG: 2004251876Speter entry = dbd_oracle_get_entry(row, n); 2005251876Speter if (entry == NULL) { 2006251876Speter return APR_ENOENT; 2007251876Speter } 2008251876Speter *(apr_int64_t*)data = apr_atoi64(entry); 2009251876Speter break; 2010251876Speter case APR_DBD_TYPE_ULONGLONG: 2011251876Speter entry = dbd_oracle_get_entry(row, n); 2012251876Speter if (entry == NULL) { 2013251876Speter return APR_ENOENT; 2014251876Speter } 2015251876Speter *(apr_uint64_t*)data = apr_atoi64(entry); 2016251876Speter break; 2017251876Speter case APR_DBD_TYPE_FLOAT: 2018251876Speter entry = dbd_oracle_get_entry(row, n); 2019251876Speter if (entry == NULL) { 2020251876Speter return APR_ENOENT; 2021251876Speter } 2022251876Speter *(float*)data = (float)atof(entry); 2023251876Speter break; 2024251876Speter case APR_DBD_TYPE_DOUBLE: 2025251876Speter entry = dbd_oracle_get_entry(row, n); 2026251876Speter if (entry == NULL) { 2027251876Speter return APR_ENOENT; 2028251876Speter } 2029251876Speter *(double*)data = atof(entry); 2030251876Speter break; 2031251876Speter case APR_DBD_TYPE_STRING: 2032251876Speter case APR_DBD_TYPE_TEXT: 2033251876Speter case APR_DBD_TYPE_TIME: 2034251876Speter case APR_DBD_TYPE_DATE: 2035251876Speter case APR_DBD_TYPE_DATETIME: 2036251876Speter case APR_DBD_TYPE_TIMESTAMP: 2037251876Speter case APR_DBD_TYPE_ZTIMESTAMP: 2038251876Speter entry = dbd_oracle_get_entry(row, n); 2039251876Speter if (entry == NULL) { 2040251876Speter return APR_ENOENT; 2041251876Speter } 2042251876Speter *(char**)data = (char*)entry; 2043251876Speter break; 2044251876Speter case APR_DBD_TYPE_BLOB: 2045251876Speter case APR_DBD_TYPE_CLOB: 2046251876Speter { 2047251876Speter apr_bucket *e; 2048251876Speter apr_bucket_brigade *b = (apr_bucket_brigade*)data; 2049251876Speter apr_dbd_t *sql = row->res->handle; 2050251876Speter ub4 len = 0; 2051251876Speter 2052251876Speter switch (val->type) { 2053251876Speter case SQLT_BLOB: 2054251876Speter case SQLT_CLOB: 2055251876Speter sql->status = OCILobGetLength(sql->svc, sql->err, 2056251876Speter val->buf.lobval, &len); 2057251876Speter switch(sql->status) { 2058251876Speter case OCI_SUCCESS: 2059251876Speter case OCI_SUCCESS_WITH_INFO: 2060251876Speter if (len == 0) { 2061251876Speter e = apr_bucket_eos_create(b->bucket_alloc); 2062251876Speter } 2063251876Speter else { 2064251876Speter e = apr_bucket_lob_create(row, n, 0, len, 2065251876Speter row->pool, b->bucket_alloc); 2066251876Speter } 2067251876Speter break; 2068251876Speter default: 2069251876Speter return APR_ENOENT; 2070251876Speter } 2071251876Speter break; 2072251876Speter default: 2073251876Speter entry = dbd_oracle_get_entry(row, n); 2074251876Speter if (entry == NULL) { 2075251876Speter return APR_ENOENT; 2076251876Speter } 2077251876Speter e = apr_bucket_pool_create(entry, strlen(entry), 2078251876Speter row->pool, b->bucket_alloc); 2079251876Speter break; 2080251876Speter } 2081251876Speter APR_BRIGADE_INSERT_TAIL(b, e); 2082251876Speter } 2083251876Speter break; 2084251876Speter case APR_DBD_TYPE_NULL: 2085251876Speter *(void**)data = NULL; 2086251876Speter break; 2087251876Speter default: 2088251876Speter return APR_EGENERAL; 2089251876Speter } 2090251876Speter 2091251876Speter return APR_SUCCESS; 2092251876Speter} 2093251876Speter 2094251876Speterstatic apr_status_t dbd_oracle_close(apr_dbd_t *handle) 2095251876Speter{ 2096251876Speter /* FIXME: none of the oracle docs/examples say anything about 2097251876Speter * closing/releasing handles. Which seems unlikely ... 2098251876Speter */ 2099251876Speter 2100251876Speter /* OK, let's grab from cdemo again. 2101251876Speter * cdemo81 does nothing; cdemo82 does OCIHandleFree on the handles 2102251876Speter */ 2103251876Speter switch (OCISessionEnd(handle->svc, handle->err, handle->auth, 2104251876Speter (ub4)OCI_DEFAULT)) { 2105251876Speter default: 2106251876Speter break; 2107251876Speter } 2108251876Speter switch (OCIServerDetach(handle->svr, handle->err, (ub4) OCI_DEFAULT )) { 2109251876Speter default: 2110251876Speter break; 2111251876Speter } 2112251876Speter /* does OCISessionEnd imply this? */ 2113251876Speter switch (OCIHandleFree((dvoid *) handle->auth, (ub4) OCI_HTYPE_SESSION)) { 2114251876Speter default: 2115251876Speter break; 2116251876Speter } 2117251876Speter switch (OCIHandleFree((dvoid *) handle->svr, (ub4) OCI_HTYPE_SERVER)) { 2118251876Speter default: 2119251876Speter break; 2120251876Speter } 2121251876Speter switch (OCIHandleFree((dvoid *) handle->svc, (ub4) OCI_HTYPE_SVCCTX)) { 2122251876Speter default: 2123251876Speter break; 2124251876Speter } 2125251876Speter switch (OCIHandleFree((dvoid *) handle->err, (ub4) OCI_HTYPE_ERROR)) { 2126251876Speter default: 2127251876Speter break; 2128251876Speter } 2129251876Speter return APR_SUCCESS; 2130251876Speter} 2131251876Speter 2132251876Speterstatic apr_status_t dbd_oracle_check_conn(apr_pool_t *pool, apr_dbd_t *sql) 2133251876Speter{ 2134251876Speter apr_dbd_results_t *res = NULL; 2135251876Speter apr_dbd_row_t *row = NULL; 2136251876Speter 2137251876Speter if(dbd_oracle_pselect(pool, sql, &res, sql->check_conn_stmt, 2138251876Speter 0, NULL) != 0) { 2139251876Speter return APR_EGENERAL; 2140251876Speter } 2141251876Speter 2142251876Speter if(dbd_oracle_get_row(pool, res, &row, -1) != 0) { 2143251876Speter return APR_EGENERAL; 2144251876Speter } 2145251876Speter 2146251876Speter if(dbd_oracle_get_row(pool, res, &row, -1) != -1) { 2147251876Speter return APR_EGENERAL; 2148251876Speter } 2149251876Speter 2150251876Speter return APR_SUCCESS; 2151251876Speter} 2152251876Speter 2153251876Speterstatic int dbd_oracle_select_db(apr_pool_t *pool, apr_dbd_t *handle, 2154251876Speter const char *name) 2155251876Speter{ 2156251876Speter /* FIXME: need to find this in the docs */ 2157251876Speter return APR_ENOTIMPL; 2158251876Speter} 2159251876Speter 2160251876Speterstatic void *dbd_oracle_native(apr_dbd_t *handle) 2161251876Speter{ 2162251876Speter /* FIXME: can we do anything better? Oracle doesn't seem to have 2163251876Speter * a concept of a handle in the sense we use it. 2164251876Speter */ 2165251876Speter return dbd_oracle_env; 2166251876Speter} 2167251876Speter 2168251876Speterstatic int dbd_oracle_num_cols(apr_dbd_results_t* res) 2169251876Speter{ 2170251876Speter return res->statement->nout; 2171251876Speter} 2172251876Speter 2173251876Speterstatic int dbd_oracle_num_tuples(apr_dbd_results_t* res) 2174251876Speter{ 2175251876Speter if (!res->seek) { 2176251876Speter return -1; 2177251876Speter } 2178251876Speter if (res->nrows >= 0) { 2179251876Speter return res->nrows; 2180251876Speter } 2181251876Speter res->handle->status = OCIAttrGet(res->statement->stmt, OCI_HTYPE_STMT, 2182251876Speter &res->nrows, 0, OCI_ATTR_ROW_COUNT, 2183251876Speter res->handle->err); 2184251876Speter return res->nrows; 2185251876Speter} 2186251876Speter 2187251876SpeterAPU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_oracle_driver = { 2188251876Speter "oracle", 2189251876Speter dbd_oracle_init, 2190251876Speter dbd_oracle_native, 2191251876Speter dbd_oracle_open, 2192251876Speter dbd_oracle_check_conn, 2193251876Speter dbd_oracle_close, 2194251876Speter dbd_oracle_select_db, 2195251876Speter dbd_oracle_start_transaction, 2196251876Speter dbd_oracle_end_transaction, 2197251876Speter dbd_oracle_query, 2198251876Speter dbd_oracle_select, 2199251876Speter dbd_oracle_num_cols, 2200251876Speter dbd_oracle_num_tuples, 2201251876Speter dbd_oracle_get_row, 2202251876Speter dbd_oracle_get_entry, 2203251876Speter dbd_oracle_error, 2204251876Speter dbd_oracle_escape, 2205251876Speter dbd_oracle_prepare, 2206251876Speter dbd_oracle_pvquery, 2207251876Speter dbd_oracle_pvselect, 2208251876Speter dbd_oracle_pquery, 2209251876Speter dbd_oracle_pselect, 2210251876Speter dbd_oracle_get_name, 2211251876Speter dbd_oracle_transaction_mode_get, 2212251876Speter dbd_oracle_transaction_mode_set, 2213251876Speter ":apr%d", 2214251876Speter dbd_oracle_pvbquery, 2215251876Speter dbd_oracle_pvbselect, 2216251876Speter dbd_oracle_pbquery, 2217251876Speter dbd_oracle_pbselect, 2218251876Speter dbd_oracle_datum_get 2219251876Speter}; 2220251876Speter#endif 2221