Return to oci_driver.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / pdo_oci |
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: */