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 if (H->err) { 231 OCIHandleFree(H->err, OCI_HTYPE_ERROR); 232 H->err = NULL; 233 } 234 235 if (H->charset && H->env) { 236 OCIHandleFree(H->env, OCI_HTYPE_ENV); 237 H->env = NULL; 238 } 239 240 if (H->einfo.errmsg) { 241 pefree(H->einfo.errmsg, dbh->is_persistent); 242 H->einfo.errmsg = NULL; 243 } 244 245 pefree(H, dbh->is_persistent); 246 247 return 0; 248} 249/* }}} */ 250 251static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC) /* {{{ */ 252{ 253 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 254 pdo_oci_stmt *S = ecalloc(1, sizeof(*S)); 255 ub4 prefetch; 256 char *nsql = NULL; 257 int nsql_len = 0; 258 int ret; 259 260#if HAVE_OCISTMTFETCH2 261 S->exec_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, 262 PDO_CURSOR_FWDONLY TSRMLS_CC) == PDO_CURSOR_SCROLL ? 263 OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT; 264#else 265 S->exec_type = OCI_DEFAULT; 266#endif 267 268 S->H = H; 269 stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED; 270 ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC); 271 272 if (ret == 1) { 273 /* query was re-written */ 274 sql = nsql; 275 sql_len = nsql_len; 276 } else if (ret == -1) { 277 /* couldn't grok it */ 278 strcpy(dbh->error_code, stmt->error_code); 279 efree(S); 280 return 0; 281 } 282 283 /* create an OCI statement handle */ 284 OCIHandleAlloc(H->env, (dvoid*)&S->stmt, OCI_HTYPE_STMT, 0, NULL); 285 286 /* and our own private error handle */ 287 OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL); 288 289 if (sql_len) { 290 H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT); 291 if (nsql) { 292 efree(nsql); 293 nsql = NULL; 294 } 295 if (H->last_err) { 296 H->last_err = oci_drv_error("OCIStmtPrepare"); 297 OCIHandleFree(S->stmt, OCI_HTYPE_STMT); 298 OCIHandleFree(S->err, OCI_HTYPE_ERROR); 299 efree(S); 300 return 0; 301 } 302 303 } 304 305 prefetch = pdo_oci_sanitize_prefetch(pdo_attr_lval(driver_options, PDO_ATTR_PREFETCH, PDO_OCI_PREFETCH_DEFAULT TSRMLS_CC)); 306 if (prefetch) { 307 H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0, 308 OCI_ATTR_PREFETCH_ROWS, H->err); 309 if (!H->last_err) { 310 prefetch *= PDO_OCI_PREFETCH_ROWSIZE; 311 H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0, 312 OCI_ATTR_PREFETCH_MEMORY, H->err); 313 } 314 } 315 316 stmt->driver_data = S; 317 stmt->methods = &oci_stmt_methods; 318 if (nsql) { 319 efree(nsql); 320 nsql = NULL; 321 } 322 323 return 1; 324} 325/* }}} */ 326 327static long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */ 328{ 329 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 330 OCIStmt *stmt; 331 ub2 stmt_type; 332 ub4 rowcount; 333 int ret = -1; 334 335 OCIHandleAlloc(H->env, (dvoid*)&stmt, OCI_HTYPE_STMT, 0, NULL); 336 337 H->last_err = OCIStmtPrepare(stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT); 338 if (H->last_err) { 339 H->last_err = oci_drv_error("OCIStmtPrepare"); 340 OCIHandleFree(stmt, OCI_HTYPE_STMT); 341 return -1; 342 } 343 344 H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, H->err); 345 346 if (stmt_type == OCI_STMT_SELECT) { 347 /* invalid usage; cancel it */ 348 OCIHandleFree(stmt, OCI_HTYPE_STMT); 349 php_error_docref(NULL TSRMLS_CC, E_WARNING, "issuing a SELECT query here is invalid"); 350 return -1; 351 } 352 353 /* now we are good to go */ 354 H->last_err = OCIStmtExecute(H->svc, stmt, H->err, 1, 0, NULL, NULL, 355 (dbh->auto_commit && !dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); 356 357 if (H->last_err) { 358 H->last_err = oci_drv_error("OCIStmtExecute"); 359 } else { 360 /* return the number of affected rows */ 361 H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, H->err); 362 ret = rowcount; 363 } 364 365 OCIHandleFree(stmt, OCI_HTYPE_STMT); 366 367 return ret; 368} 369/* }}} */ 370 371static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC) /* {{{ */ 372{ 373 int qcount = 0; 374 char const *cu, *l, *r; 375 char *c; 376 377 if (!unquotedlen) { 378 *quotedlen = 2; 379 *quoted = emalloc(*quotedlen+1); 380 strcpy(*quoted, "''"); 381 return 1; 382 } 383 384 /* count single quotes */ 385 for (cu = unquoted; (cu = strchr(cu,'\'')); qcount++, cu++) 386 ; /* empty loop */ 387 388 *quotedlen = unquotedlen + qcount + 2; 389 *quoted = c = emalloc(*quotedlen+1); 390 *c++ = '\''; 391 392 /* foreach (chunk that ends in a quote) */ 393 for (l = unquoted; (r = strchr(l,'\'')); l = r+1) { 394 strncpy(c, l, r-l+1); 395 c += (r-l+1); 396 *c++ = '\''; /* add second quote */ 397 } 398 399 /* Copy remainder and add enclosing quote */ 400 strncpy(c, l, *quotedlen-(c-*quoted)-1); 401 (*quoted)[*quotedlen-1] = '\''; 402 (*quoted)[*quotedlen] = '\0'; 403 404 return 1; 405} 406/* }}} */ 407 408static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ 409{ 410 /* with Oracle, there is nothing special to be done */ 411 return 1; 412} 413/* }}} */ 414 415static int oci_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ 416{ 417 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 418 419 H->last_err = OCITransCommit(H->svc, H->err, 0); 420 421 if (H->last_err) { 422 H->last_err = oci_drv_error("OCITransCommit"); 423 return 0; 424 } 425 return 1; 426} 427/* }}} */ 428 429static int oci_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ 430{ 431 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 432 433 H->last_err = OCITransRollback(H->svc, H->err, 0); 434 435 if (H->last_err) { 436 H->last_err = oci_drv_error("OCITransRollback"); 437 return 0; 438 } 439 return 1; 440} 441/* }}} */ 442 443static int oci_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */ 444{ 445 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 446 447 if (attr == PDO_ATTR_AUTOCOMMIT) { 448 if (dbh->in_txn) { 449 /* Assume they want to commit whatever is outstanding */ 450 H->last_err = OCITransCommit(H->svc, H->err, 0); 451 452 if (H->last_err) { 453 H->last_err = oci_drv_error("OCITransCommit"); 454 return 0; 455 } 456 dbh->in_txn = 0; 457 } 458 459 convert_to_long(val); 460 461 dbh->auto_commit = Z_LVAL_P(val); 462 return 1; 463 } else { 464 return 0; 465 } 466 467} 468/* }}} */ 469 470static int oci_handle_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC) /* {{{ */ 471{ 472 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 473 474 switch (attr) { 475 case PDO_ATTR_SERVER_VERSION: 476 case PDO_ATTR_SERVER_INFO: 477 { 478 text infostr[512]; 479 char verstr[15]; 480 ub4 vernum; 481 482 if (OCIServerRelease(H->svc, H->err, infostr, (ub4)sizeof(infostr), (ub1)OCI_HTYPE_SVCCTX, &vernum)) 483 { 484 ZVAL_STRING(return_value, "<<Unknown>>", 1); 485 } else { 486 if (attr == PDO_ATTR_SERVER_INFO) { 487 ZVAL_STRING(return_value, (char *)infostr, 1); 488 } else { 489 slprintf(verstr, sizeof(verstr), "%d.%d.%d.%d.%d", 490 (int)((vernum>>24) & 0xFF), /* version number */ 491 (int)((vernum>>20) & 0x0F), /* release number*/ 492 (int)((vernum>>12) & 0xFF), /* update number */ 493 (int)((vernum>>8) & 0x0F), /* port release number */ 494 (int)((vernum>>0) & 0xFF)); /* port update number */ 495 496 ZVAL_STRING(return_value, verstr, 1); 497 } 498 } 499 return TRUE; 500 } 501 502 case PDO_ATTR_CLIENT_VERSION: 503 { 504#if OCI_MAJOR_VERSION > 10 || (OCI_MAJOR_VERSION == 10 && OCI_MINOR_VERSION >= 2) 505 /* Run time client version */ 506 sword major, minor, update, patch, port_update; 507 char verstr[15]; 508 509 OCIClientVersion(&major, &minor, &update, &patch, &port_update); 510 slprintf(verstr, sizeof(verstr), "%d.%d.%d.%d.%d", major, minor, update, patch, port_update); 511 ZVAL_STRING(return_value, verstr, 1); 512#elif defined(PHP_PDO_OCI_CLIENT_VERSION) 513 /* Compile time client version */ 514 ZVAL_STRING(return_value, PHP_PDO_OCI_CLIENT_VERSION, 1); 515#else 516 return FALSE; 517 518#endif /* Check for OCIClientVersion() support */ 519 520 return TRUE; 521 } 522 523 case PDO_ATTR_AUTOCOMMIT: 524 ZVAL_BOOL(return_value, dbh->auto_commit); 525 return TRUE; 526 527 default: 528 return FALSE; 529 530 } 531 return FALSE; 532 533} 534/* }}} */ 535 536static int pdo_oci_check_liveness(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ 537{ 538 pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; 539 sb4 error_code = 0; 540 char version[256]; 541 542 /* TODO move attached check to PDO level */ 543 if (H->attached == 0) { 544 return FAILURE; 545 } 546 /* TODO add persistent_timeout check at PDO level */ 547 548 549 /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation) 550 * such as from Pre-10.1 servers, the error is still from the server and we would have 551 * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for 552 * Pre-10.2 clients 553 */ 554#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */ 555 H->last_err = OCIPing (H->svc, H->err, OCI_DEFAULT); 556#else 557 /* use good old OCIServerVersion() */ 558 H->last_err = OCIServerVersion (H->svc, H->err, (text *)version, sizeof(version), OCI_HTYPE_SVCCTX); 559#endif 560 if (H->last_err == OCI_SUCCESS) { 561 return SUCCESS; 562 } 563 564 OCIErrorGet (H->err, (ub4)1, NULL, &error_code, NULL, 0, OCI_HTYPE_ERROR); 565 566 if (error_code == 1010) { 567 return SUCCESS; 568 } 569 return FAILURE; 570} 571/* }}} */ 572 573static struct pdo_dbh_methods oci_methods = { 574 oci_handle_closer, 575 oci_handle_preparer, 576 oci_handle_doer, 577 oci_handle_quoter, 578 oci_handle_begin, 579 oci_handle_commit, 580 oci_handle_rollback, 581 oci_handle_set_attribute, 582 NULL, 583 pdo_oci_fetch_error_func, 584 oci_handle_get_attribute, 585 pdo_oci_check_liveness, /* check_liveness */ 586 NULL /* get_driver_methods */ 587}; 588 589static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ 590{ 591 pdo_oci_db_handle *H; 592 int i, ret = 0; 593 struct pdo_data_src_parser vars[] = { 594 { "charset", NULL, 0 }, 595 { "dbname", "", 0 } 596 }; 597 598 php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2); 599 600 H = pecalloc(1, sizeof(*H), dbh->is_persistent); 601 dbh->driver_data = H; 602 603 /* allocate an environment */ 604#if HAVE_OCIENVNLSCREATE 605 if (vars[0].optval) { 606 H->charset = OCINlsCharSetNameToId(pdo_oci_Env, (const oratext *)vars[0].optval); 607 if (!H->charset) { 608 oci_init_error("OCINlsCharSetNameToId: unknown character set name"); 609 goto cleanup; 610 } else { 611 if (OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset) != OCI_SUCCESS) { 612 oci_init_error("OCIEnvNlsCreate: Check the character set is valid and that PHP has access to Oracle libraries and NLS data"); 613 goto cleanup; 614 } 615 } 616 } 617#endif 618 if (H->env == NULL) { 619 /* use the global environment */ 620 H->env = pdo_oci_Env; 621 } 622 623 /* something to hold errors */ 624 OCIHandleAlloc(H->env, (dvoid **)&H->err, OCI_HTYPE_ERROR, 0, NULL); 625 626 /* handle for the server */ 627 OCIHandleAlloc(H->env, (dvoid **)&H->server, OCI_HTYPE_SERVER, 0, NULL); 628 629 H->last_err = OCIServerAttach(H->server, H->err, (text*)vars[1].optval, 630 strlen(vars[1].optval), OCI_DEFAULT); 631 632 if (H->last_err) { 633 oci_drv_error("pdo_oci_handle_factory"); 634 goto cleanup; 635 } 636 637 H->attached = 1; 638 639 /* create a service context */ 640 H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->svc, OCI_HTYPE_SVCCTX, 0, NULL); 641 if (H->last_err) { 642 oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SVCCTX"); 643 goto cleanup; 644 } 645 646 H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->session, OCI_HTYPE_SESSION, 0, NULL); 647 if (H->last_err) { 648 oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SESSION"); 649 goto cleanup; 650 } 651 652 /* set server handle into service handle */ 653 H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->server, 0, OCI_ATTR_SERVER, H->err); 654 if (H->last_err) { 655 oci_drv_error("OCIAttrSet: OCI_ATTR_SERVER"); 656 goto cleanup; 657 } 658 659 /* username */ 660 if (dbh->username) { 661 H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION, 662 dbh->username, strlen(dbh->username), 663 OCI_ATTR_USERNAME, H->err); 664 if (H->last_err) { 665 oci_drv_error("OCIAttrSet: OCI_ATTR_USERNAME"); 666 goto cleanup; 667 } 668 } 669 670 /* password */ 671 if (dbh->password) { 672 H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION, 673 dbh->password, strlen(dbh->password), 674 OCI_ATTR_PASSWORD, H->err); 675 if (H->last_err) { 676 oci_drv_error("OCIAttrSet: OCI_ATTR_PASSWORD"); 677 goto cleanup; 678 } 679 } 680 681 /* Now fire up the session */ 682 H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT); 683 if (H->last_err) { 684 oci_drv_error("OCISessionBegin"); 685 goto cleanup; 686 } 687 688 /* set the server handle into service handle */ 689 H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err); 690 if (H->last_err) { 691 oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION"); 692 goto cleanup; 693 } 694 695 dbh->methods = &oci_methods; 696 dbh->alloc_own_columns = 1; 697 dbh->native_case = PDO_CASE_UPPER; 698 699 ret = 1; 700 701cleanup: 702 for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) { 703 if (vars[i].freeme) { 704 efree(vars[i].optval); 705 } 706 } 707 708 if (!ret) { 709 oci_handle_closer(dbh TSRMLS_CC); 710 } 711 712 return ret; 713} 714/* }}} */ 715 716pdo_driver_t pdo_oci_driver = { 717 PDO_DRIVER_HEADER(oci), 718 pdo_oci_handle_factory 719}; 720 721static inline ub4 pdo_oci_sanitize_prefetch(long prefetch) /* {{{ */ 722{ 723 if (prefetch < 0) { 724 prefetch = 0; 725 } else if (prefetch > UB4MAXVAL / PDO_OCI_PREFETCH_ROWSIZE) { 726 prefetch = PDO_OCI_PREFETCH_DEFAULT; 727 } 728 return ((ub4)prefetch); 729} 730/* }}} */ 731 732 733/* 734 * Local variables: 735 * tab-width: 4 736 * c-basic-offset: 4 737 * End: 738 * vim600: noet sw=4 ts=4 fdm=marker 739 * vim<600: noet sw=4 ts=4 740 */ 741