Annotation of embedaddon/php/ext/pdo_oci/oci_driver.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Author: Wez Furlong <wez@php.net> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: oci_driver.c 321634 2012-01-01 13:15:04Z felipe $ */
! 20:
! 21: #ifdef HAVE_CONFIG_H
! 22: #include "config.h"
! 23: #endif
! 24:
! 25: #include "php.h"
! 26: #include "php_ini.h"
! 27: #include "ext/standard/info.h"
! 28: #include "pdo/php_pdo.h"
! 29: #include "pdo/php_pdo_driver.h"
! 30: #include "php_pdo_oci.h"
! 31: #include "php_pdo_oci_int.h"
! 32: #include "Zend/zend_exceptions.h"
! 33:
! 34: static inline ub4 pdo_oci_sanitize_prefetch(long prefetch);
! 35:
! 36: static int pdo_oci_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */
! 37: {
! 38: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 39: pdo_oci_error_info *einfo;
! 40:
! 41: einfo = &H->einfo;
! 42:
! 43: if (stmt) {
! 44: pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
! 45:
! 46: if (S->einfo.errmsg) {
! 47: einfo = &S->einfo;
! 48: }
! 49: }
! 50:
! 51: if (einfo->errcode) {
! 52: add_next_index_long(info, einfo->errcode);
! 53: add_next_index_string(info, einfo->errmsg, 1);
! 54: }
! 55:
! 56: return 1;
! 57: }
! 58: /* }}} */
! 59:
! 60: ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line TSRMLS_DC) /* {{{ */
! 61: {
! 62: text errbuf[1024] = "<<Unknown>>";
! 63: char tmp_buf[2048];
! 64: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 65: pdo_oci_error_info *einfo;
! 66: pdo_oci_stmt *S = NULL;
! 67: pdo_error_type *pdo_err = &dbh->error_code;
! 68:
! 69: if (stmt) {
! 70: S = (pdo_oci_stmt*)stmt->driver_data;
! 71: einfo = &S->einfo;
! 72: pdo_err = &stmt->error_code;
! 73: }
! 74: else {
! 75: einfo = &H->einfo;
! 76: }
! 77:
! 78: if (einfo->errmsg) {
! 79: pefree(einfo->errmsg, dbh->is_persistent);
! 80: }
! 81:
! 82: einfo->errmsg = NULL;
! 83: einfo->errcode = 0;
! 84: einfo->file = file;
! 85: einfo->line = line;
! 86:
! 87: if (isinit) { /* Initialization error */
! 88: strcpy(*pdo_err, "HY000");
! 89: slprintf(tmp_buf, sizeof(tmp_buf), "%s (%s:%d)", what, file, line);
! 90: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 91: }
! 92: else {
! 93: switch (status) {
! 94: case OCI_SUCCESS:
! 95: strcpy(*pdo_err, "00000");
! 96: break;
! 97: case OCI_ERROR:
! 98: OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
! 99: slprintf(tmp_buf, sizeof(tmp_buf), "%s: %s (%s:%d)", what, errbuf, file, line);
! 100: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 101: break;
! 102: case OCI_SUCCESS_WITH_INFO:
! 103: OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
! 104: slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_SUCCESS_WITH_INFO: %s (%s:%d)", what, errbuf, file, line);
! 105: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 106: break;
! 107: case OCI_NEED_DATA:
! 108: slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_NEED_DATA (%s:%d)", what, file, line);
! 109: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 110: break;
! 111: case OCI_NO_DATA:
! 112: slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_NO_DATA (%s:%d)", what, file, line);
! 113: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 114: break;
! 115: case OCI_INVALID_HANDLE:
! 116: slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_INVALID_HANDLE (%s:%d)", what, file, line);
! 117: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 118: break;
! 119: case OCI_STILL_EXECUTING:
! 120: slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_STILL_EXECUTING (%s:%d)", what, file, line);
! 121: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 122: break;
! 123: case OCI_CONTINUE:
! 124: slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_CONTINUE (%s:%d)", what, file, line);
! 125: einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
! 126: break;
! 127: }
! 128:
! 129: if (einfo->errcode) {
! 130: switch (einfo->errcode) {
! 131: case 1013: /* user requested cancel of current operation */
! 132: zend_bailout();
! 133: break;
! 134:
! 135: #if 0
! 136: case 955: /* ORA-00955: name is already used by an existing object */
! 137: *pdo_err = PDO_ERR_ALREADY_EXISTS;
! 138: break;
! 139: #endif
! 140:
! 141: case 12154: /* ORA-12154: TNS:could not resolve service name */
! 142: strcpy(*pdo_err, "42S02");
! 143: break;
! 144:
! 145: case 22: /* ORA-00022: invalid session id */
! 146: case 378:
! 147: case 602:
! 148: case 603:
! 149: case 604:
! 150: case 609:
! 151: case 1012: /* ORA-01012: */
! 152: case 1033:
! 153: case 1041:
! 154: case 1043:
! 155: case 1089:
! 156: case 1090:
! 157: case 1092:
! 158: case 3113: /* ORA-03133: end of file on communication channel */
! 159: case 3114:
! 160: case 3122:
! 161: case 3135:
! 162: case 12153:
! 163: case 27146:
! 164: case 28511:
! 165: /* consider the connection closed */
! 166: dbh->is_closed = 1;
! 167: H->attached = 0;
! 168: strcpy(*pdo_err, "01002"); /* FIXME */
! 169: break;
! 170:
! 171: default:
! 172: strcpy(*pdo_err, "HY000");
! 173: }
! 174: }
! 175:
! 176: if (stmt) {
! 177: /* always propogate the error code back up to the dbh,
! 178: * so that we can catch the error information when execute
! 179: * is called via query. See Bug #33707 */
! 180: if (H->einfo.errmsg) {
! 181: pefree(H->einfo.errmsg, dbh->is_persistent);
! 182: }
! 183: H->einfo = *einfo;
! 184: H->einfo.errmsg = einfo->errmsg ? pestrdup(einfo->errmsg, dbh->is_persistent) : NULL;
! 185: strcpy(dbh->error_code, stmt->error_code);
! 186: }
! 187: }
! 188:
! 189: /* little mini hack so that we can use this code from the dbh ctor */
! 190: if (!dbh->methods) {
! 191: zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s]: %s", *pdo_err, einfo->errmsg);
! 192: }
! 193:
! 194: return einfo->errcode;
! 195: }
! 196: /* }}} */
! 197:
! 198: static int oci_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
! 199: {
! 200: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 201:
! 202: if (H->svc) {
! 203: /* rollback any outstanding work */
! 204: OCITransRollback(H->svc, H->err, 0);
! 205: }
! 206:
! 207: if (H->session) {
! 208: OCIHandleFree(H->session, OCI_HTYPE_SESSION);
! 209: H->session = NULL;
! 210: }
! 211:
! 212: if (H->svc) {
! 213: OCIHandleFree(H->svc, OCI_HTYPE_SVCCTX);
! 214: H->svc = NULL;
! 215: }
! 216:
! 217: if (H->server && H->attached) {
! 218: H->last_err = OCIServerDetach(H->server, H->err, OCI_DEFAULT);
! 219: if (H->last_err) {
! 220: oci_drv_error("OCIServerDetach");
! 221: }
! 222: H->attached = 0;
! 223: }
! 224:
! 225: if (H->server) {
! 226: OCIHandleFree(H->server, OCI_HTYPE_SERVER);
! 227: H->server = NULL;
! 228: }
! 229:
! 230: OCIHandleFree(H->err, OCI_HTYPE_ERROR);
! 231: H->err = NULL;
! 232:
! 233: if (H->charset && H->env) {
! 234: OCIHandleFree(H->env, OCI_HTYPE_ENV);
! 235: H->env = NULL;
! 236: }
! 237:
! 238: if (H->einfo.errmsg) {
! 239: pefree(H->einfo.errmsg, dbh->is_persistent);
! 240: H->einfo.errmsg = NULL;
! 241: }
! 242:
! 243: pefree(H, dbh->is_persistent);
! 244:
! 245: return 0;
! 246: }
! 247: /* }}} */
! 248:
! 249: static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC) /* {{{ */
! 250: {
! 251: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 252: pdo_oci_stmt *S = ecalloc(1, sizeof(*S));
! 253: ub4 prefetch;
! 254: char *nsql = NULL;
! 255: int nsql_len = 0;
! 256: int ret;
! 257:
! 258: #if HAVE_OCISTMTFETCH2
! 259: S->exec_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR,
! 260: PDO_CURSOR_FWDONLY TSRMLS_CC) == PDO_CURSOR_SCROLL ?
! 261: OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT;
! 262: #else
! 263: S->exec_type = OCI_DEFAULT;
! 264: #endif
! 265:
! 266: S->H = H;
! 267: stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
! 268: ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
! 269:
! 270: if (ret == 1) {
! 271: /* query was re-written */
! 272: sql = nsql;
! 273: sql_len = nsql_len;
! 274: } else if (ret == -1) {
! 275: /* couldn't grok it */
! 276: strcpy(dbh->error_code, stmt->error_code);
! 277: efree(S);
! 278: return 0;
! 279: }
! 280:
! 281: /* create an OCI statement handle */
! 282: OCIHandleAlloc(H->env, (dvoid*)&S->stmt, OCI_HTYPE_STMT, 0, NULL);
! 283:
! 284: /* and our own private error handle */
! 285: OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL);
! 286:
! 287: if (sql_len) {
! 288: H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
! 289: if (nsql) {
! 290: efree(nsql);
! 291: nsql = NULL;
! 292: }
! 293: if (H->last_err) {
! 294: H->last_err = oci_drv_error("OCIStmtPrepare");
! 295: OCIHandleFree(S->stmt, OCI_HTYPE_STMT);
! 296: OCIHandleFree(S->err, OCI_HTYPE_ERROR);
! 297: efree(S);
! 298: return 0;
! 299: }
! 300:
! 301: }
! 302:
! 303: prefetch = pdo_oci_sanitize_prefetch(pdo_attr_lval(driver_options, PDO_ATTR_PREFETCH, PDO_OCI_PREFETCH_DEFAULT TSRMLS_CC));
! 304: if (prefetch) {
! 305: H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
! 306: OCI_ATTR_PREFETCH_ROWS, H->err);
! 307: if (!H->last_err) {
! 308: prefetch *= PDO_OCI_PREFETCH_ROWSIZE;
! 309: H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
! 310: OCI_ATTR_PREFETCH_MEMORY, H->err);
! 311: }
! 312: }
! 313:
! 314: stmt->driver_data = S;
! 315: stmt->methods = &oci_stmt_methods;
! 316: if (nsql) {
! 317: efree(nsql);
! 318: nsql = NULL;
! 319: }
! 320:
! 321: return 1;
! 322: }
! 323: /* }}} */
! 324:
! 325: static long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */
! 326: {
! 327: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 328: OCIStmt *stmt;
! 329: ub2 stmt_type;
! 330: ub4 rowcount;
! 331: int ret = -1;
! 332:
! 333: OCIHandleAlloc(H->env, (dvoid*)&stmt, OCI_HTYPE_STMT, 0, NULL);
! 334:
! 335: H->last_err = OCIStmtPrepare(stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
! 336: if (H->last_err) {
! 337: H->last_err = oci_drv_error("OCIStmtPrepare");
! 338: OCIHandleFree(stmt, OCI_HTYPE_STMT);
! 339: return -1;
! 340: }
! 341:
! 342: H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, H->err);
! 343:
! 344: if (stmt_type == OCI_STMT_SELECT) {
! 345: /* invalid usage; cancel it */
! 346: OCIHandleFree(stmt, OCI_HTYPE_STMT);
! 347: php_error_docref(NULL TSRMLS_CC, E_WARNING, "issuing a SELECT query here is invalid");
! 348: return -1;
! 349: }
! 350:
! 351: /* now we are good to go */
! 352: H->last_err = OCIStmtExecute(H->svc, stmt, H->err, 1, 0, NULL, NULL,
! 353: (dbh->auto_commit && !dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
! 354:
! 355: if (H->last_err) {
! 356: H->last_err = oci_drv_error("OCIStmtExecute");
! 357: } else {
! 358: /* return the number of affected rows */
! 359: H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, H->err);
! 360: ret = rowcount;
! 361: }
! 362:
! 363: OCIHandleFree(stmt, OCI_HTYPE_STMT);
! 364:
! 365: return ret;
! 366: }
! 367: /* }}} */
! 368:
! 369: static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC) /* {{{ */
! 370: {
! 371: int qcount = 0;
! 372: char const *cu, *l, *r;
! 373: char *c;
! 374:
! 375: if (!unquotedlen) {
! 376: *quotedlen = 2;
! 377: *quoted = emalloc(*quotedlen+1);
! 378: strcpy(*quoted, "''");
! 379: return 1;
! 380: }
! 381:
! 382: /* count single quotes */
! 383: for (cu = unquoted; (cu = strchr(cu,'\'')); qcount++, cu++)
! 384: ; /* empty loop */
! 385:
! 386: *quotedlen = unquotedlen + qcount + 2;
! 387: *quoted = c = emalloc(*quotedlen+1);
! 388: *c++ = '\'';
! 389:
! 390: /* foreach (chunk that ends in a quote) */
! 391: for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {
! 392: strncpy(c, l, r-l+1);
! 393: c += (r-l+1);
! 394: *c++ = '\''; /* add second quote */
! 395: }
! 396:
! 397: /* Copy remainder and add enclosing quote */
! 398: strncpy(c, l, *quotedlen-(c-*quoted)-1);
! 399: (*quoted)[*quotedlen-1] = '\'';
! 400: (*quoted)[*quotedlen] = '\0';
! 401:
! 402: return 1;
! 403: }
! 404: /* }}} */
! 405:
! 406: static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
! 407: {
! 408: /* with Oracle, there is nothing special to be done */
! 409: return 1;
! 410: }
! 411: /* }}} */
! 412:
! 413: static int oci_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
! 414: {
! 415: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 416:
! 417: H->last_err = OCITransCommit(H->svc, H->err, 0);
! 418:
! 419: if (H->last_err) {
! 420: H->last_err = oci_drv_error("OCITransCommit");
! 421: return 0;
! 422: }
! 423: return 1;
! 424: }
! 425: /* }}} */
! 426:
! 427: static int oci_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
! 428: {
! 429: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 430:
! 431: H->last_err = OCITransRollback(H->svc, H->err, 0);
! 432:
! 433: if (H->last_err) {
! 434: H->last_err = oci_drv_error("OCITransRollback");
! 435: return 0;
! 436: }
! 437: return 1;
! 438: }
! 439: /* }}} */
! 440:
! 441: static int oci_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */
! 442: {
! 443: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 444:
! 445: if (attr == PDO_ATTR_AUTOCOMMIT) {
! 446: if (dbh->in_txn) {
! 447: /* Assume they want to commit whatever is outstanding */
! 448: H->last_err = OCITransCommit(H->svc, H->err, 0);
! 449:
! 450: if (H->last_err) {
! 451: H->last_err = oci_drv_error("OCITransCommit");
! 452: return 0;
! 453: }
! 454: dbh->in_txn = 0;
! 455: }
! 456:
! 457: convert_to_long(val);
! 458:
! 459: dbh->auto_commit = Z_LVAL_P(val);
! 460: return 1;
! 461: } else {
! 462: return 0;
! 463: }
! 464:
! 465: }
! 466: /* }}} */
! 467:
! 468: static int oci_handle_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC) /* {{{ */
! 469: {
! 470: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 471:
! 472: switch (attr) {
! 473: case PDO_ATTR_SERVER_VERSION:
! 474: case PDO_ATTR_SERVER_INFO:
! 475: {
! 476: text infostr[512];
! 477: char verstr[15];
! 478: ub4 vernum;
! 479:
! 480: if (OCIServerRelease(H->svc, H->err, infostr, (ub4)sizeof(infostr), (ub1)OCI_HTYPE_SVCCTX, &vernum))
! 481: {
! 482: ZVAL_STRING(return_value, "<<Unknown>>", 1);
! 483: } else {
! 484: if (attr == PDO_ATTR_SERVER_INFO) {
! 485: ZVAL_STRING(return_value, (char *)infostr, 1);
! 486: } else {
! 487: slprintf(verstr, sizeof(verstr), "%d.%d.%d.%d.%d",
! 488: (int)((vernum>>24) & 0xFF), /* version number */
! 489: (int)((vernum>>20) & 0x0F), /* release number*/
! 490: (int)((vernum>>12) & 0xFF), /* update number */
! 491: (int)((vernum>>8) & 0x0F), /* port release number */
! 492: (int)((vernum>>0) & 0xFF)); /* port update number */
! 493:
! 494: ZVAL_STRING(return_value, verstr, 1);
! 495: }
! 496: }
! 497: return TRUE;
! 498: }
! 499:
! 500: case PDO_ATTR_CLIENT_VERSION:
! 501: {
! 502: #if OCI_MAJOR_VERSION > 10 || (OCI_MAJOR_VERSION == 10 && OCI_MINOR_VERSION >= 2)
! 503: /* Run time client version */
! 504: sword major, minor, update, patch, port_update;
! 505: char verstr[15];
! 506:
! 507: OCIClientVersion(&major, &minor, &update, &patch, &port_update);
! 508: slprintf(verstr, sizeof(verstr), "%d.%d.%d.%d.%d", major, minor, update, patch, port_update);
! 509: ZVAL_STRING(return_value, verstr, 1);
! 510: #elif defined(PHP_PDO_OCI_CLIENT_VERSION)
! 511: /* Compile time client version */
! 512: ZVAL_STRING(return_value, PHP_PDO_OCI_CLIENT_VERSION, 1);
! 513: #else
! 514: return FALSE;
! 515:
! 516: #endif /* Check for OCIClientVersion() support */
! 517:
! 518: return TRUE;
! 519: }
! 520:
! 521: case PDO_ATTR_AUTOCOMMIT:
! 522: ZVAL_BOOL(return_value, dbh->auto_commit);
! 523: return TRUE;
! 524:
! 525: default:
! 526: return FALSE;
! 527:
! 528: }
! 529: return FALSE;
! 530:
! 531: }
! 532: /* }}} */
! 533:
! 534: static int pdo_oci_check_liveness(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
! 535: {
! 536: pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
! 537: sb4 error_code = 0;
! 538: char version[256];
! 539:
! 540: /* TODO move attached check to PDO level */
! 541: if (H->attached == 0) {
! 542: return FAILURE;
! 543: }
! 544: /* TODO add persistent_timeout check at PDO level */
! 545:
! 546:
! 547: /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
! 548: * such as from Pre-10.1 servers, the error is still from the server and we would have
! 549: * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
! 550: * Pre-10.2 clients
! 551: */
! 552: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
! 553: H->last_err = OCIPing (H->svc, H->err, OCI_DEFAULT);
! 554: #else
! 555: /* use good old OCIServerVersion() */
! 556: H->last_err = OCIServerVersion (H->svc, H->err, (text *)version, sizeof(version), OCI_HTYPE_SVCCTX);
! 557: #endif
! 558: if (H->last_err == OCI_SUCCESS) {
! 559: return SUCCESS;
! 560: }
! 561:
! 562: OCIErrorGet (H->err, (ub4)1, NULL, &error_code, NULL, 0, OCI_HTYPE_ERROR);
! 563:
! 564: if (error_code == 1010) {
! 565: return SUCCESS;
! 566: }
! 567: return FAILURE;
! 568: }
! 569: /* }}} */
! 570:
! 571: static struct pdo_dbh_methods oci_methods = {
! 572: oci_handle_closer,
! 573: oci_handle_preparer,
! 574: oci_handle_doer,
! 575: oci_handle_quoter,
! 576: oci_handle_begin,
! 577: oci_handle_commit,
! 578: oci_handle_rollback,
! 579: oci_handle_set_attribute,
! 580: NULL,
! 581: pdo_oci_fetch_error_func,
! 582: oci_handle_get_attribute,
! 583: pdo_oci_check_liveness, /* check_liveness */
! 584: NULL /* get_driver_methods */
! 585: };
! 586:
! 587: static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
! 588: {
! 589: pdo_oci_db_handle *H;
! 590: int i, ret = 0;
! 591: struct pdo_data_src_parser vars[] = {
! 592: { "charset", NULL, 0 },
! 593: { "dbname", "", 0 }
! 594: };
! 595:
! 596: php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2);
! 597:
! 598: H = pecalloc(1, sizeof(*H), dbh->is_persistent);
! 599: dbh->driver_data = H;
! 600:
! 601: /* allocate an environment */
! 602: #if HAVE_OCIENVNLSCREATE
! 603: if (vars[0].optval) {
! 604: H->charset = OCINlsCharSetNameToId(pdo_oci_Env, (const oratext *)vars[0].optval);
! 605: if (!H->charset) {
! 606: oci_init_error("OCINlsCharSetNameToId: unknown character set name");
! 607: goto cleanup;
! 608: } else {
! 609: if (OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset) != OCI_SUCCESS) {
! 610: oci_init_error("OCIEnvNlsCreate: Check the character set is valid and that PHP has access to Oracle libraries and NLS data");
! 611: goto cleanup;
! 612: }
! 613: }
! 614: }
! 615: #endif
! 616: if (H->env == NULL) {
! 617: /* use the global environment */
! 618: H->env = pdo_oci_Env;
! 619: }
! 620:
! 621: /* something to hold errors */
! 622: OCIHandleAlloc(H->env, (dvoid **)&H->err, OCI_HTYPE_ERROR, 0, NULL);
! 623:
! 624: /* handle for the server */
! 625: OCIHandleAlloc(H->env, (dvoid **)&H->server, OCI_HTYPE_SERVER, 0, NULL);
! 626:
! 627: H->last_err = OCIServerAttach(H->server, H->err, (text*)vars[1].optval,
! 628: strlen(vars[1].optval), OCI_DEFAULT);
! 629:
! 630: if (H->last_err) {
! 631: oci_drv_error("pdo_oci_handle_factory");
! 632: goto cleanup;
! 633: }
! 634:
! 635: H->attached = 1;
! 636:
! 637: /* create a service context */
! 638: H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->svc, OCI_HTYPE_SVCCTX, 0, NULL);
! 639: if (H->last_err) {
! 640: oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SVCCTX");
! 641: goto cleanup;
! 642: }
! 643:
! 644: H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->session, OCI_HTYPE_SESSION, 0, NULL);
! 645: if (H->last_err) {
! 646: oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SESSION");
! 647: goto cleanup;
! 648: }
! 649:
! 650: /* set server handle into service handle */
! 651: H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->server, 0, OCI_ATTR_SERVER, H->err);
! 652: if (H->last_err) {
! 653: oci_drv_error("OCIAttrSet: OCI_ATTR_SERVER");
! 654: goto cleanup;
! 655: }
! 656:
! 657: /* username */
! 658: if (dbh->username) {
! 659: H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
! 660: dbh->username, strlen(dbh->username),
! 661: OCI_ATTR_USERNAME, H->err);
! 662: if (H->last_err) {
! 663: oci_drv_error("OCIAttrSet: OCI_ATTR_USERNAME");
! 664: goto cleanup;
! 665: }
! 666: }
! 667:
! 668: /* password */
! 669: if (dbh->password) {
! 670: H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
! 671: dbh->password, strlen(dbh->password),
! 672: OCI_ATTR_PASSWORD, H->err);
! 673: if (H->last_err) {
! 674: oci_drv_error("OCIAttrSet: OCI_ATTR_PASSWORD");
! 675: goto cleanup;
! 676: }
! 677: }
! 678:
! 679: /* Now fire up the session */
! 680: H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT);
! 681: if (H->last_err) {
! 682: oci_drv_error("OCISessionBegin");
! 683: goto cleanup;
! 684: }
! 685:
! 686: /* set the server handle into service handle */
! 687: H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err);
! 688: if (H->last_err) {
! 689: oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION");
! 690: goto cleanup;
! 691: }
! 692:
! 693: dbh->methods = &oci_methods;
! 694: dbh->alloc_own_columns = 1;
! 695: dbh->native_case = PDO_CASE_UPPER;
! 696:
! 697: ret = 1;
! 698:
! 699: cleanup:
! 700: for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
! 701: if (vars[i].freeme) {
! 702: efree(vars[i].optval);
! 703: }
! 704: }
! 705:
! 706: if (!ret) {
! 707: oci_handle_closer(dbh TSRMLS_CC);
! 708: }
! 709:
! 710: return ret;
! 711: }
! 712: /* }}} */
! 713:
! 714: pdo_driver_t pdo_oci_driver = {
! 715: PDO_DRIVER_HEADER(oci),
! 716: pdo_oci_handle_factory
! 717: };
! 718:
! 719: static inline ub4 pdo_oci_sanitize_prefetch(long prefetch) /* {{{ */
! 720: {
! 721: if (prefetch < 0) {
! 722: prefetch = 0;
! 723: } else if (prefetch > UB4MAXVAL / PDO_OCI_PREFETCH_ROWSIZE) {
! 724: prefetch = PDO_OCI_PREFETCH_DEFAULT;
! 725: }
! 726: return ((ub4)prefetch);
! 727: }
! 728: /* }}} */
! 729:
! 730:
! 731: /*
! 732: * Local variables:
! 733: * tab-width: 4
! 734: * c-basic-offset: 4
! 735: * End:
! 736: * vim600: noet sw=4 ts=4 fdm=marker
! 737: * vim<600: noet sw=4 ts=4
! 738: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>