1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 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$ */ 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 34static inline ub4 pdo_oci_sanitize_prefetch(long prefetch); 35 36static 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 60ub4 _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 198static 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 249static 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 325static 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 369static 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 406static 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 413static 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 427static 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 441static 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 468static 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 534static 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 571static 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 587static 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 699cleanup: 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 714pdo_driver_t pdo_oci_driver = { 715 PDO_DRIVER_HEADER(oci), 716 pdo_oci_handle_factory 717}; 718 719static 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 */ 739