Annotation of embedaddon/php/ext/pdo_pgsql/pgsql_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: | Authors: Edin Kadribasic <edink@emini.dk> |
! 16: | Ilia Alshanestsky <ilia@prohost.org> |
! 17: | Wez Furlong <wez@php.net> |
! 18: +----------------------------------------------------------------------+
! 19: */
! 20:
! 21: /* $Id: pgsql_driver.c 321634 2012-01-01 13:15:04Z felipe $ */
! 22:
! 23: #ifdef HAVE_CONFIG_H
! 24: #include "config.h"
! 25: #endif
! 26:
! 27: #include "php.h"
! 28: #include "php_ini.h"
! 29: #include "ext/standard/info.h"
! 30: #include "pdo/php_pdo.h"
! 31: #include "pdo/php_pdo_driver.h"
! 32: #include "ext/standard/file.h"
! 33:
! 34: #undef PACKAGE_BUGREPORT
! 35: #undef PACKAGE_NAME
! 36: #undef PACKAGE_STRING
! 37: #undef PACKAGE_TARNAME
! 38: #undef PACKAGE_VERSION
! 39: #include "pg_config.h" /* needed for PG_VERSION */
! 40: #include "php_pdo_pgsql.h"
! 41: #include "php_pdo_pgsql_int.h"
! 42: #include "zend_exceptions.h"
! 43:
! 44: static char * _pdo_pgsql_trim_message(const char *message, int persistent)
! 45: {
! 46: register int i = strlen(message)-1;
! 47: char *tmp;
! 48:
! 49: if (i>1 && (message[i-1] == '\r' || message[i-1] == '\n') && message[i] == '.') {
! 50: --i;
! 51: }
! 52: while (i>0 && (message[i] == '\r' || message[i] == '\n')) {
! 53: --i;
! 54: }
! 55: ++i;
! 56: tmp = pemalloc(i + 1, persistent);
! 57: memcpy(tmp, message, i);
! 58: tmp[i] = '\0';
! 59:
! 60: return tmp;
! 61: }
! 62:
! 63: int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *file, int line TSRMLS_DC) /* {{{ */
! 64: {
! 65: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 66: pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
! 67: pdo_pgsql_error_info *einfo = &H->einfo;
! 68: char *errmsg = PQerrorMessage(H->server);
! 69:
! 70: einfo->errcode = errcode;
! 71: einfo->file = file;
! 72: einfo->line = line;
! 73:
! 74: if (einfo->errmsg) {
! 75: pefree(einfo->errmsg, dbh->is_persistent);
! 76: einfo->errmsg = NULL;
! 77: }
! 78:
! 79: if (sqlstate == NULL) {
! 80: strcpy(*pdo_err, "HY000");
! 81: }
! 82: else {
! 83: strcpy(*pdo_err, sqlstate);
! 84: }
! 85:
! 86: if (errmsg) {
! 87: einfo->errmsg = _pdo_pgsql_trim_message(errmsg, dbh->is_persistent);
! 88: }
! 89:
! 90: if (!dbh->methods) {
! 91: zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
! 92: *pdo_err, einfo->errcode, einfo->errmsg);
! 93: }
! 94:
! 95: return errcode;
! 96: }
! 97: /* }}} */
! 98:
! 99: static void _pdo_pgsql_notice(pdo_dbh_t *dbh, const char *message) /* {{{ */
! 100: {
! 101: /* pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; */
! 102: }
! 103: /* }}} */
! 104:
! 105: static int pdo_pgsql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */
! 106: {
! 107: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 108: pdo_pgsql_error_info *einfo = &H->einfo;
! 109:
! 110: if (einfo->errcode) {
! 111: add_next_index_long(info, einfo->errcode);
! 112: add_next_index_string(info, einfo->errmsg, 1);
! 113: }
! 114:
! 115: return 1;
! 116: }
! 117: /* }}} */
! 118:
! 119: /* {{{ pdo_pgsql_create_lob_stream */
! 120: static size_t pgsql_lob_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
! 121: {
! 122: struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
! 123: return lo_write(self->conn, self->lfd, (char*)buf, count);
! 124: }
! 125:
! 126: static size_t pgsql_lob_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
! 127: {
! 128: struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
! 129: return lo_read(self->conn, self->lfd, buf, count);
! 130: }
! 131:
! 132: static int pgsql_lob_close(php_stream *stream, int close_handle TSRMLS_DC)
! 133: {
! 134: struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
! 135: pdo_dbh_t *dbh = self->dbh;
! 136:
! 137: if (close_handle) {
! 138: lo_close(self->conn, self->lfd);
! 139: }
! 140: efree(self);
! 141: php_pdo_dbh_delref(dbh TSRMLS_CC);
! 142: return 0;
! 143: }
! 144:
! 145: static int pgsql_lob_flush(php_stream *stream TSRMLS_DC)
! 146: {
! 147: return 0;
! 148: }
! 149:
! 150: static int pgsql_lob_seek(php_stream *stream, off_t offset, int whence,
! 151: off_t *newoffset TSRMLS_DC)
! 152: {
! 153: struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract;
! 154: int pos = lo_lseek(self->conn, self->lfd, offset, whence);
! 155: *newoffset = pos;
! 156: return pos >= 0 ? 0 : -1;
! 157: }
! 158:
! 159: php_stream_ops pdo_pgsql_lob_stream_ops = {
! 160: pgsql_lob_write,
! 161: pgsql_lob_read,
! 162: pgsql_lob_close,
! 163: pgsql_lob_flush,
! 164: "pdo_pgsql lob stream",
! 165: pgsql_lob_seek,
! 166: NULL,
! 167: NULL,
! 168: NULL
! 169: };
! 170:
! 171: php_stream *pdo_pgsql_create_lob_stream(pdo_dbh_t *dbh, int lfd, Oid oid TSRMLS_DC)
! 172: {
! 173: php_stream *stm;
! 174: struct pdo_pgsql_lob_self *self = ecalloc(1, sizeof(*self));
! 175: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 176:
! 177: self->dbh = dbh;
! 178: self->lfd = lfd;
! 179: self->oid = oid;
! 180: self->conn = H->server;
! 181:
! 182: stm = php_stream_alloc(&pdo_pgsql_lob_stream_ops, self, 0, "r+b");
! 183:
! 184: if (stm) {
! 185: php_pdo_dbh_addref(dbh TSRMLS_CC);
! 186: return stm;
! 187: }
! 188:
! 189: efree(self);
! 190: return NULL;
! 191: }
! 192: /* }}} */
! 193:
! 194: static int pgsql_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
! 195: {
! 196: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 197: if (H) {
! 198: if (H->server) {
! 199: PQfinish(H->server);
! 200: H->server = NULL;
! 201: }
! 202: if (H->einfo.errmsg) {
! 203: pefree(H->einfo.errmsg, dbh->is_persistent);
! 204: H->einfo.errmsg = NULL;
! 205: }
! 206: pefree(H, dbh->is_persistent);
! 207: dbh->driver_data = NULL;
! 208: }
! 209: return 0;
! 210: }
! 211: /* }}} */
! 212:
! 213: static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
! 214: {
! 215: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 216: pdo_pgsql_stmt *S = ecalloc(1, sizeof(pdo_pgsql_stmt));
! 217: int scrollable;
! 218: #if HAVE_PQPREPARE
! 219: int ret;
! 220: char *nsql = NULL;
! 221: int nsql_len = 0;
! 222: int emulate = 0;
! 223: #endif
! 224:
! 225: S->H = H;
! 226: stmt->driver_data = S;
! 227: stmt->methods = &pgsql_stmt_methods;
! 228:
! 229: scrollable = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR,
! 230: PDO_CURSOR_FWDONLY TSRMLS_CC) == PDO_CURSOR_SCROLL;
! 231:
! 232: if (scrollable) {
! 233: if (S->cursor_name) {
! 234: efree(S->cursor_name);
! 235: }
! 236: spprintf(&S->cursor_name, 0, "pdo_crsr_%08x", ++H->stmt_counter);
! 237: #if HAVE_PQPREPARE
! 238: emulate = 1;
! 239: #endif
! 240: }
! 241:
! 242: #if HAVE_PQPREPARE
! 243: else if (driver_options) {
! 244: if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, H->disable_native_prepares TSRMLS_CC) == 1 ||
! 245: pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) {
! 246: emulate = 1;
! 247: }
! 248: } else {
! 249: emulate = H->disable_native_prepares || H->emulate_prepares;
! 250: }
! 251:
! 252: if (!emulate && PQprotocolVersion(H->server) > 2) {
! 253: stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
! 254: stmt->named_rewrite_template = "$%d";
! 255: ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
! 256:
! 257: if (ret == 1) {
! 258: /* query was re-written */
! 259: sql = nsql;
! 260: } else if (ret == -1) {
! 261: /* couldn't grok it */
! 262: strcpy(dbh->error_code, stmt->error_code);
! 263: return 0;
! 264: }
! 265:
! 266: spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter);
! 267: /* that's all for now; we'll defer the actual prepare until the first execute call */
! 268:
! 269: if (nsql) {
! 270: S->query = nsql;
! 271: } else {
! 272: S->query = estrdup(sql);
! 273: }
! 274:
! 275: return 1;
! 276: }
! 277: #endif
! 278:
! 279: stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
! 280: return 1;
! 281: }
! 282:
! 283: static long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
! 284: {
! 285: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 286: PGresult *res;
! 287: long ret = 1;
! 288: ExecStatusType qs;
! 289:
! 290: if (!(res = PQexec(H->server, sql))) {
! 291: /* fatal error */
! 292: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL);
! 293: return -1;
! 294: }
! 295: qs = PQresultStatus(res);
! 296: if (qs != PGRES_COMMAND_OK && qs != PGRES_TUPLES_OK) {
! 297: pdo_pgsql_error(dbh, qs, pdo_pgsql_sqlstate(res));
! 298: PQclear(res);
! 299: return -1;
! 300: }
! 301: H->pgoid = PQoidValue(res);
! 302: ret = atol(PQcmdTuples(res));
! 303: PQclear(res);
! 304:
! 305: return ret;
! 306: }
! 307:
! 308: static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
! 309: {
! 310: unsigned char *escaped;
! 311: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 312: size_t tmp_len;
! 313:
! 314: switch (paramtype) {
! 315: case PDO_PARAM_LOB:
! 316: /* escapedlen returned by PQescapeBytea() accounts for trailing 0 */
! 317: #ifdef HAVE_PQESCAPE_BYTEA_CONN
! 318: escaped = PQescapeByteaConn(H->server, unquoted, unquotedlen, &tmp_len);
! 319: #else
! 320: escaped = PQescapeBytea(unquoted, unquotedlen, &tmp_len);
! 321: #endif
! 322: *quotedlen = (int)tmp_len + 1;
! 323: *quoted = emalloc(*quotedlen + 1);
! 324: memcpy((*quoted)+1, escaped, *quotedlen-2);
! 325: (*quoted)[0] = '\'';
! 326: (*quoted)[*quotedlen-1] = '\'';
! 327: (*quoted)[*quotedlen] = '\0';
! 328: PQfreemem(escaped);
! 329: break;
! 330: default:
! 331: *quoted = safe_emalloc(2, unquotedlen, 3);
! 332: (*quoted)[0] = '\'';
! 333: #ifndef HAVE_PQESCAPE_CONN
! 334: *quotedlen = PQescapeString(*quoted + 1, unquoted, unquotedlen);
! 335: #else
! 336: *quotedlen = PQescapeStringConn(H->server, *quoted + 1, unquoted, unquotedlen, NULL);
! 337: #endif
! 338: (*quoted)[*quotedlen + 1] = '\'';
! 339: (*quoted)[*quotedlen + 2] = '\0';
! 340: *quotedlen += 2;
! 341: }
! 342: return 1;
! 343: }
! 344:
! 345: static char *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
! 346: {
! 347: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 348: char *id = NULL;
! 349:
! 350: if (name == NULL) {
! 351: if (H->pgoid == InvalidOid) {
! 352: return NULL;
! 353: }
! 354: *len = spprintf(&id, 0, "%ld", (long) H->pgoid);
! 355: } else {
! 356: PGresult *res;
! 357: ExecStatusType status;
! 358: const char *q[1];
! 359: q[0] = name;
! 360: res = PQexecParams(H->server, "SELECT CURRVAL($1)", 1, NULL, q, NULL, NULL, 0);
! 361: status = PQresultStatus(res);
! 362:
! 363: if (res && (status == PGRES_TUPLES_OK)) {
! 364: id = estrdup((char *)PQgetvalue(res, 0, 0));
! 365: *len = PQgetlength(res, 0, 0);
! 366: } else {
! 367: pdo_pgsql_error(dbh, status, pdo_pgsql_sqlstate(res));
! 368: }
! 369:
! 370: if (res) {
! 371: PQclear(res);
! 372: }
! 373: }
! 374: return id;
! 375: }
! 376:
! 377: static int pdo_pgsql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
! 378: {
! 379: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 380:
! 381: switch (attr) {
! 382: case PDO_ATTR_CLIENT_VERSION:
! 383: ZVAL_STRING(return_value, PG_VERSION, 1);
! 384: break;
! 385:
! 386: case PDO_ATTR_SERVER_VERSION:
! 387: if (PQprotocolVersion(H->server) >= 3) { /* PostgreSQL 7.4 or later */
! 388: ZVAL_STRING(return_value, (char*)PQparameterStatus(H->server, "server_version"), 1);
! 389: } else /* emulate above via a query */
! 390: {
! 391: PGresult *res = PQexec(H->server, "SELECT VERSION()");
! 392: if (res && PQresultStatus(res) == PGRES_TUPLES_OK) {
! 393: ZVAL_STRING(return_value, (char *)PQgetvalue(res, 0, 0), 1);
! 394: }
! 395:
! 396: if (res) {
! 397: PQclear(res);
! 398: }
! 399: }
! 400: break;
! 401:
! 402: case PDO_ATTR_CONNECTION_STATUS:
! 403: switch (PQstatus(H->server)) {
! 404: case CONNECTION_STARTED:
! 405: ZVAL_STRINGL(return_value, "Waiting for connection to be made.", sizeof("Waiting for connection to be made.")-1, 1);
! 406: break;
! 407:
! 408: case CONNECTION_MADE:
! 409: case CONNECTION_OK:
! 410: ZVAL_STRINGL(return_value, "Connection OK; waiting to send.", sizeof("Connection OK; waiting to send.")-1, 1);
! 411: break;
! 412:
! 413: case CONNECTION_AWAITING_RESPONSE:
! 414: ZVAL_STRINGL(return_value, "Waiting for a response from the server.", sizeof("Waiting for a response from the server.")-1, 1);
! 415: break;
! 416:
! 417: case CONNECTION_AUTH_OK:
! 418: ZVAL_STRINGL(return_value, "Received authentication; waiting for backend start-up to finish.", sizeof("Received authentication; waiting for backend start-up to finish.")-1, 1);
! 419: break;
! 420: #ifdef CONNECTION_SSL_STARTUP
! 421: case CONNECTION_SSL_STARTUP:
! 422: ZVAL_STRINGL(return_value, "Negotiating SSL encryption.", sizeof("Negotiating SSL encryption.")-1, 1);
! 423: break;
! 424: #endif
! 425: case CONNECTION_SETENV:
! 426: ZVAL_STRINGL(return_value, "Negotiating environment-driven parameter settings.", sizeof("Negotiating environment-driven parameter settings.")-1, 1);
! 427: break;
! 428:
! 429: case CONNECTION_BAD:
! 430: default:
! 431: ZVAL_STRINGL(return_value, "Bad connection.", sizeof("Bad connection.")-1, 1);
! 432: break;
! 433: }
! 434: break;
! 435:
! 436: case PDO_ATTR_SERVER_INFO: {
! 437: int spid = PQbackendPID(H->server);
! 438: char *tmp;
! 439: spprintf(&tmp, 0,
! 440: "PID: %d; Client Encoding: %s; Is Superuser: %s; Session Authorization: %s; Date Style: %s",
! 441: spid,
! 442: (char*)PQparameterStatus(H->server, "client_encoding"),
! 443: (char*)PQparameterStatus(H->server, "is_superuser"),
! 444: (char*)PQparameterStatus(H->server, "session_authorization"),
! 445: (char*)PQparameterStatus(H->server, "DateStyle"));
! 446: ZVAL_STRING(return_value, tmp, 0);
! 447: }
! 448: break;
! 449:
! 450: default:
! 451: return 0;
! 452: }
! 453:
! 454: return 1;
! 455: }
! 456:
! 457: /* {{{ */
! 458: static int pdo_pgsql_check_liveness(pdo_dbh_t *dbh TSRMLS_DC)
! 459: {
! 460: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 461: if (PQstatus(H->server) == CONNECTION_BAD) {
! 462: PQreset(H->server);
! 463: }
! 464: return (PQstatus(H->server) == CONNECTION_OK) ? SUCCESS : FAILURE;
! 465: }
! 466: /* }}} */
! 467:
! 468: static int pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC)
! 469: {
! 470: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 471: PGresult *res;
! 472: int ret = 1;
! 473:
! 474: res = PQexec(H->server, cmd);
! 475:
! 476: if (PQresultStatus(res) != PGRES_COMMAND_OK) {
! 477: pdo_pgsql_error(dbh, PQresultStatus(res), pdo_pgsql_sqlstate(res));
! 478: ret = 0;
! 479: }
! 480:
! 481: PQclear(res);
! 482: return ret;
! 483: }
! 484:
! 485: static int pgsql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
! 486: {
! 487: return pdo_pgsql_transaction_cmd("BEGIN", dbh TSRMLS_CC);
! 488: }
! 489:
! 490: static int pgsql_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
! 491: {
! 492: return pdo_pgsql_transaction_cmd("COMMIT", dbh TSRMLS_CC);
! 493: }
! 494:
! 495: static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
! 496: {
! 497: return pdo_pgsql_transaction_cmd("ROLLBACK", dbh TSRMLS_CC);
! 498: }
! 499:
! 500: /* {{{ proto string PDO::pgsqlCopyFromArray(string $table_name , array $rows [, string $delimiter [, string $null_as ] [, string $fields])
! 501: Returns true if the copy worked fine or false if error */
! 502: static PHP_METHOD(PDO, pgsqlCopyFromArray)
! 503: {
! 504: pdo_dbh_t *dbh;
! 505: pdo_pgsql_db_handle *H;
! 506:
! 507: zval *pg_rows;
! 508:
! 509: char *table_name, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL;
! 510: int table_name_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len;
! 511: char *query;
! 512:
! 513: PGresult *pgsql_result;
! 514: ExecStatusType status;
! 515:
! 516: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/a|sss",
! 517: &table_name, &table_name_len, &pg_rows,
! 518: &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
! 519: return;
! 520: }
! 521:
! 522: if (!zend_hash_num_elements(Z_ARRVAL_P(pg_rows))) {
! 523: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot copy from an empty array");
! 524: RETURN_FALSE;
! 525: }
! 526:
! 527: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 528: PDO_CONSTRUCT_CHECK;
! 529:
! 530: if (pg_fields) {
! 531: spprintf(&query, 0, "COPY %s (%s) FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 532: } else {
! 533: spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 534: }
! 535:
! 536: /* Obtain db Handle */
! 537: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 538:
! 539: while ((pgsql_result = PQgetResult(H->server))) {
! 540: PQclear(pgsql_result);
! 541: }
! 542: pgsql_result = PQexec(H->server, query);
! 543:
! 544: efree(query);
! 545: query = NULL;
! 546:
! 547: if (pgsql_result) {
! 548: status = PQresultStatus(pgsql_result);
! 549: } else {
! 550: status = (ExecStatusType) PQstatus(H->server);
! 551: }
! 552:
! 553: if (status == PGRES_COPY_IN && pgsql_result) {
! 554: int command_failed = 0;
! 555: int buffer_len = 0;
! 556: zval **tmp;
! 557: HashPosition pos;
! 558:
! 559: PQclear(pgsql_result);
! 560: zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(pg_rows), &pos);
! 561: while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
! 562: int query_len;
! 563: convert_to_string_ex(tmp);
! 564:
! 565: if (buffer_len < Z_STRLEN_PP(tmp)) {
! 566: buffer_len = Z_STRLEN_PP(tmp);
! 567: query = erealloc(query, buffer_len + 2); /* room for \n\0 */
! 568: }
! 569: memcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
! 570: query_len = Z_STRLEN_PP(tmp);
! 571: if (query[query_len - 1] != '\n') {
! 572: query[query_len++] = '\n';
! 573: }
! 574: query[query_len] = '\0';
! 575: if (PQputCopyData(H->server, query, query_len) != 1) {
! 576: efree(query);
! 577: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "copy failed");
! 578: RETURN_FALSE;
! 579: }
! 580: zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
! 581: }
! 582: if (query) {
! 583: efree(query);
! 584: }
! 585:
! 586: if (PQputCopyEnd(H->server, NULL) != 1) {
! 587: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "putcopyend failed");
! 588: RETURN_FALSE;
! 589: }
! 590:
! 591: while ((pgsql_result = PQgetResult(H->server))) {
! 592: if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
! 593: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
! 594: command_failed = 1;
! 595: }
! 596: PQclear(pgsql_result);
! 597: }
! 598:
! 599: RETURN_BOOL(!command_failed);
! 600: } else {
! 601: PQclear(pgsql_result);
! 602: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
! 603: RETURN_FALSE;
! 604: }
! 605: }
! 606: /* }}} */
! 607:
! 608: /* {{{ proto string PDO::pgsqlCopyFromFile(string $table_name , string $filename [, string $delimiter [, string $null_as ] [, string $fields])
! 609: Returns true if the copy worked fine or false if error */
! 610: static PHP_METHOD(PDO, pgsqlCopyFromFile)
! 611: {
! 612: pdo_dbh_t *dbh;
! 613: pdo_pgsql_db_handle *H;
! 614:
! 615: char *table_name, *filename, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL;
! 616: int table_name_len, filename_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len;
! 617: char *query;
! 618: PGresult *pgsql_result;
! 619: ExecStatusType status;
! 620: php_stream *stream;
! 621:
! 622: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sss",
! 623: &table_name, &table_name_len, &filename, &filename_len,
! 624: &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
! 625: return;
! 626: }
! 627:
! 628: /* Obtain db Handler */
! 629: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 630: PDO_CONSTRUCT_CHECK;
! 631:
! 632: stream = php_stream_open_wrapper_ex(filename, "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, FG(default_context));
! 633: if (!stream) {
! 634: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to open the file");
! 635: RETURN_FALSE;
! 636: }
! 637:
! 638: if (pg_fields) {
! 639: spprintf(&query, 0, "COPY %s (%s) FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 640: } else {
! 641: spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 642: }
! 643:
! 644: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 645:
! 646: while ((pgsql_result = PQgetResult(H->server))) {
! 647: PQclear(pgsql_result);
! 648: }
! 649: pgsql_result = PQexec(H->server, query);
! 650:
! 651: efree(query);
! 652:
! 653: if (pgsql_result) {
! 654: status = PQresultStatus(pgsql_result);
! 655: } else {
! 656: status = (ExecStatusType) PQstatus(H->server);
! 657: }
! 658:
! 659: if (status == PGRES_COPY_IN && pgsql_result) {
! 660: char *buf;
! 661: int command_failed = 0;
! 662: size_t line_len = 0;
! 663:
! 664: PQclear(pgsql_result);
! 665: while ((buf = php_stream_get_line(stream, NULL, 0, &line_len)) != NULL) {
! 666: if (PQputCopyData(H->server, buf, line_len) != 1) {
! 667: efree(buf);
! 668: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "copy failed");
! 669: php_stream_close(stream);
! 670: RETURN_FALSE;
! 671: }
! 672: efree(buf);
! 673: }
! 674: php_stream_close(stream);
! 675:
! 676: if (PQputCopyEnd(H->server, NULL) != 1) {
! 677: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "putcopyend failed");
! 678: RETURN_FALSE;
! 679: }
! 680:
! 681: while ((pgsql_result = PQgetResult(H->server))) {
! 682: if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
! 683: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
! 684: command_failed = 1;
! 685: }
! 686: PQclear(pgsql_result);
! 687: }
! 688:
! 689: RETURN_BOOL(!command_failed);
! 690: } else {
! 691: PQclear(pgsql_result);
! 692: php_stream_close(stream);
! 693: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
! 694: RETURN_FALSE;
! 695: }
! 696: }
! 697: /* }}} */
! 698:
! 699:
! 700: /* {{{ proto string PDO::pgsqlCopyToFile(string $table_name , $filename, [string $delimiter [, string $null_as [, string $fields]]])
! 701: Returns true if the copy worked fine or false if error */
! 702: static PHP_METHOD(PDO, pgsqlCopyToFile)
! 703: {
! 704: pdo_dbh_t *dbh;
! 705: pdo_pgsql_db_handle *H;
! 706:
! 707: char *table_name, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL, *filename = NULL;
! 708: int table_name_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len, filename_len;
! 709: char *query;
! 710:
! 711: PGresult *pgsql_result;
! 712: ExecStatusType status;
! 713:
! 714: php_stream *stream;
! 715:
! 716: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sss",
! 717: &table_name, &table_name_len, &filename, &filename_len,
! 718: &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
! 719: return;
! 720: }
! 721:
! 722: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 723: PDO_CONSTRUCT_CHECK;
! 724:
! 725: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 726:
! 727: stream = php_stream_open_wrapper_ex(filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, FG(default_context));
! 728: if (!stream) {
! 729: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to open the file for writing");
! 730: RETURN_FALSE;
! 731: }
! 732:
! 733: while ((pgsql_result = PQgetResult(H->server))) {
! 734: PQclear(pgsql_result);
! 735: }
! 736:
! 737: if (pg_fields) {
! 738: spprintf(&query, 0, "COPY %s (%s) TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 739: } else {
! 740: spprintf(&query, 0, "COPY %s TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 741: }
! 742: pgsql_result = PQexec(H->server, query);
! 743: efree(query);
! 744:
! 745: if (pgsql_result) {
! 746: status = PQresultStatus(pgsql_result);
! 747: } else {
! 748: status = (ExecStatusType) PQstatus(H->server);
! 749: }
! 750:
! 751: if (status == PGRES_COPY_OUT && pgsql_result) {
! 752: PQclear(pgsql_result);
! 753: while (1) {
! 754: char *csv = NULL;
! 755: int ret = PQgetCopyData(H->server, &csv, 0);
! 756:
! 757: if (ret == -1) {
! 758: break; /* done */
! 759: } else if (ret > 0) {
! 760: if (php_stream_write(stream, csv, ret) != ret) {
! 761: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to write to file");
! 762: PQfreemem(csv);
! 763: php_stream_close(stream);
! 764: RETURN_FALSE;
! 765: } else {
! 766: PQfreemem(csv);
! 767: }
! 768: } else {
! 769: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed: getline failed");
! 770: php_stream_close(stream);
! 771: RETURN_FALSE;
! 772: }
! 773: }
! 774: php_stream_close(stream);
! 775:
! 776: while ((pgsql_result = PQgetResult(H->server))) {
! 777: PQclear(pgsql_result);
! 778: }
! 779: RETURN_TRUE;
! 780: } else {
! 781: php_stream_close(stream);
! 782: PQclear(pgsql_result);
! 783: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
! 784: RETURN_FALSE;
! 785: }
! 786: }
! 787: /* }}} */
! 788:
! 789: /* {{{ proto string PDO::pgsqlCopyToArray(string $table_name , [string $delimiter [, string $null_as [, string $fields]]])
! 790: Returns true if the copy worked fine or false if error */
! 791: static PHP_METHOD(PDO, pgsqlCopyToArray)
! 792: {
! 793: pdo_dbh_t *dbh;
! 794: pdo_pgsql_db_handle *H;
! 795:
! 796: char *table_name, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL;
! 797: int table_name_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len;
! 798: char *query;
! 799:
! 800: PGresult *pgsql_result;
! 801: ExecStatusType status;
! 802:
! 803: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss",
! 804: &table_name, &table_name_len,
! 805: &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
! 806: return;
! 807: }
! 808:
! 809: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 810: PDO_CONSTRUCT_CHECK;
! 811:
! 812: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 813:
! 814: while ((pgsql_result = PQgetResult(H->server))) {
! 815: PQclear(pgsql_result);
! 816: }
! 817:
! 818: if (pg_fields) {
! 819: spprintf(&query, 0, "COPY %s (%s) TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 820: } else {
! 821: spprintf(&query, 0, "COPY %s TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
! 822: }
! 823: pgsql_result = PQexec(H->server, query);
! 824: efree(query);
! 825:
! 826: if (pgsql_result) {
! 827: status = PQresultStatus(pgsql_result);
! 828: } else {
! 829: status = (ExecStatusType) PQstatus(H->server);
! 830: }
! 831:
! 832: if (status == PGRES_COPY_OUT && pgsql_result) {
! 833: PQclear(pgsql_result);
! 834: array_init(return_value);
! 835:
! 836: while (1) {
! 837: char *csv = NULL;
! 838: int ret = PQgetCopyData(H->server, &csv, 0);
! 839: if (ret == -1) {
! 840: break; /* copy done */
! 841: } else if (ret > 0) {
! 842: add_next_index_stringl(return_value, csv, ret, 1);
! 843: PQfreemem(csv);
! 844: } else {
! 845: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed: getline failed");
! 846: RETURN_FALSE;
! 847: }
! 848: }
! 849:
! 850: while ((pgsql_result = PQgetResult(H->server))) {
! 851: PQclear(pgsql_result);
! 852: }
! 853: } else {
! 854: PQclear(pgsql_result);
! 855: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
! 856: RETURN_FALSE;
! 857: }
! 858: }
! 859: /* }}} */
! 860:
! 861:
! 862: /* {{{ proto string PDO::pgsqlLOBCreate()
! 863: Creates a new large object, returning its identifier. Must be called inside a transaction. */
! 864: static PHP_METHOD(PDO, pgsqlLOBCreate)
! 865: {
! 866: pdo_dbh_t *dbh;
! 867: pdo_pgsql_db_handle *H;
! 868: Oid lfd;
! 869:
! 870: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 871: PDO_CONSTRUCT_CHECK;
! 872:
! 873: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 874: lfd = lo_creat(H->server, INV_READ|INV_WRITE);
! 875:
! 876: if (lfd != InvalidOid) {
! 877: char *buf;
! 878: spprintf(&buf, 0, "%lu", (long) lfd);
! 879: RETURN_STRING(buf, 0);
! 880: }
! 881:
! 882: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000");
! 883: RETURN_FALSE;
! 884: }
! 885: /* }}} */
! 886:
! 887: /* {{{ proto resource PDO::pgsqlLOBOpen(string oid [, string mode = 'rb'])
! 888: Opens an existing large object stream. Must be called inside a transaction. */
! 889: static PHP_METHOD(PDO, pgsqlLOBOpen)
! 890: {
! 891: pdo_dbh_t *dbh;
! 892: pdo_pgsql_db_handle *H;
! 893: Oid oid;
! 894: int lfd;
! 895: char *oidstr;
! 896: int oidstrlen;
! 897: char *modestr = "rb";
! 898: int modestrlen;
! 899: int mode = INV_READ;
! 900: char *end_ptr;
! 901:
! 902: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
! 903: &oidstr, &oidstrlen, &modestr, &modestrlen)) {
! 904: RETURN_FALSE;
! 905: }
! 906:
! 907: oid = (Oid)strtoul(oidstr, &end_ptr, 10);
! 908: if (oid == 0 && (errno == ERANGE || errno == EINVAL)) {
! 909: RETURN_FALSE;
! 910: }
! 911:
! 912: if (strpbrk(modestr, "+w")) {
! 913: mode = INV_READ|INV_WRITE;
! 914: }
! 915:
! 916: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 917: PDO_CONSTRUCT_CHECK;
! 918:
! 919: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 920:
! 921: lfd = lo_open(H->server, oid, mode);
! 922:
! 923: if (lfd >= 0) {
! 924: php_stream *stream = pdo_pgsql_create_lob_stream(dbh, lfd, oid TSRMLS_CC);
! 925: if (stream) {
! 926: php_stream_to_zval(stream, return_value);
! 927: return;
! 928: }
! 929: } else {
! 930: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000");
! 931: }
! 932: RETURN_FALSE;
! 933: }
! 934: /* }}} */
! 935:
! 936: /* {{{ proto bool PDO::pgsqlLOBUnlink(string oid)
! 937: Deletes the large object identified by oid. Must be called inside a transaction. */
! 938: static PHP_METHOD(PDO, pgsqlLOBUnlink)
! 939: {
! 940: pdo_dbh_t *dbh;
! 941: pdo_pgsql_db_handle *H;
! 942: Oid oid;
! 943: char *oidstr, *end_ptr;
! 944: int oidlen;
! 945:
! 946: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
! 947: &oidstr, &oidlen)) {
! 948: RETURN_FALSE;
! 949: }
! 950:
! 951: oid = (Oid)strtoul(oidstr, &end_ptr, 10);
! 952: if (oid == 0 && (errno == ERANGE || errno == EINVAL)) {
! 953: RETURN_FALSE;
! 954: }
! 955:
! 956: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
! 957: PDO_CONSTRUCT_CHECK;
! 958:
! 959: H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 960:
! 961: if (1 == lo_unlink(H->server, oid)) {
! 962: RETURN_TRUE;
! 963: }
! 964: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000");
! 965: RETURN_FALSE;
! 966: }
! 967: /* }}} */
! 968:
! 969:
! 970: static const zend_function_entry dbh_methods[] = {
! 971: PHP_ME(PDO, pgsqlLOBCreate, NULL, ZEND_ACC_PUBLIC)
! 972: PHP_ME(PDO, pgsqlLOBOpen, NULL, ZEND_ACC_PUBLIC)
! 973: PHP_ME(PDO, pgsqlLOBUnlink, NULL, ZEND_ACC_PUBLIC)
! 974: PHP_ME(PDO, pgsqlCopyFromArray, NULL, ZEND_ACC_PUBLIC)
! 975: PHP_ME(PDO, pgsqlCopyFromFile, NULL, ZEND_ACC_PUBLIC)
! 976: PHP_ME(PDO, pgsqlCopyToArray, NULL, ZEND_ACC_PUBLIC)
! 977: PHP_ME(PDO, pgsqlCopyToFile, NULL, ZEND_ACC_PUBLIC)
! 978: PHP_FE_END
! 979: };
! 980:
! 981: static const zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
! 982: {
! 983: switch (kind) {
! 984: case PDO_DBH_DRIVER_METHOD_KIND_DBH:
! 985: return dbh_methods;
! 986: default:
! 987: return NULL;
! 988: }
! 989: }
! 990:
! 991: static int pdo_pgsql_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
! 992: {
! 993: pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
! 994:
! 995: switch (attr) {
! 996: #if HAVE_PQPREPARE
! 997: case PDO_ATTR_EMULATE_PREPARES:
! 998: H->emulate_prepares = Z_LVAL_P(val);
! 999: return 1;
! 1000: case PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT:
! 1001: H->disable_native_prepares = Z_LVAL_P(val);
! 1002: return 1;
! 1003: #endif
! 1004:
! 1005: default:
! 1006: return 0;
! 1007: }
! 1008: }
! 1009:
! 1010: static struct pdo_dbh_methods pgsql_methods = {
! 1011: pgsql_handle_closer,
! 1012: pgsql_handle_preparer,
! 1013: pgsql_handle_doer,
! 1014: pgsql_handle_quoter,
! 1015: pgsql_handle_begin,
! 1016: pgsql_handle_commit,
! 1017: pgsql_handle_rollback,
! 1018: pdo_pgsql_set_attr,
! 1019: pdo_pgsql_last_insert_id,
! 1020: pdo_pgsql_fetch_error_func,
! 1021: pdo_pgsql_get_attribute,
! 1022: pdo_pgsql_check_liveness, /* check_liveness */
! 1023: pdo_pgsql_get_driver_methods, /* get_driver_methods */
! 1024: NULL,
! 1025: };
! 1026:
! 1027: static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
! 1028: {
! 1029: pdo_pgsql_db_handle *H;
! 1030: int ret = 0;
! 1031: char *conn_str, *p, *e;
! 1032: long connect_timeout = 30;
! 1033:
! 1034: H = pecalloc(1, sizeof(pdo_pgsql_db_handle), dbh->is_persistent);
! 1035: dbh->driver_data = H;
! 1036:
! 1037: H->einfo.errcode = 0;
! 1038: H->einfo.errmsg = NULL;
! 1039:
! 1040: /* PostgreSQL wants params in the connect string to be separated by spaces,
! 1041: * if the PDO standard semicolons are used, we convert them to spaces
! 1042: */
! 1043: e = (char *) dbh->data_source + strlen(dbh->data_source);
! 1044: p = (char *) dbh->data_source;
! 1045: while ((p = memchr(p, ';', (e - p)))) {
! 1046: *p = ' ';
! 1047: }
! 1048:
! 1049: if (driver_options) {
! 1050: connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30 TSRMLS_CC);
! 1051: }
! 1052:
! 1053: /* support both full connection string & connection string + login and/or password */
! 1054: if (dbh->username && dbh->password) {
! 1055: spprintf(&conn_str, 0, "%s user=%s password=%s connect_timeout=%ld", dbh->data_source, dbh->username, dbh->password, connect_timeout);
! 1056: } else if (dbh->username) {
! 1057: spprintf(&conn_str, 0, "%s user=%s connect_timeout=%ld", dbh->data_source, dbh->username, connect_timeout);
! 1058: } else if (dbh->password) {
! 1059: spprintf(&conn_str, 0, "%s password=%s connect_timeout=%ld", dbh->data_source, dbh->password, connect_timeout);
! 1060: } else {
! 1061: spprintf(&conn_str, 0, "%s connect_timeout=%ld", (char *) dbh->data_source, connect_timeout);
! 1062: }
! 1063:
! 1064: H->server = PQconnectdb(conn_str);
! 1065:
! 1066: efree(conn_str);
! 1067:
! 1068: if (PQstatus(H->server) != CONNECTION_OK) {
! 1069: pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, PHP_PDO_PGSQL_CONNECTION_FAILURE_SQLSTATE);
! 1070: goto cleanup;
! 1071: }
! 1072:
! 1073: PQsetNoticeProcessor(H->server, (void(*)(void*,const char*))_pdo_pgsql_notice, (void *)&dbh);
! 1074:
! 1075: H->attached = 1;
! 1076: H->pgoid = -1;
! 1077:
! 1078: dbh->methods = &pgsql_methods;
! 1079: dbh->alloc_own_columns = 1;
! 1080: dbh->max_escaped_char_length = 2;
! 1081:
! 1082: ret = 1;
! 1083:
! 1084: cleanup:
! 1085: dbh->methods = &pgsql_methods;
! 1086: if (!ret) {
! 1087: pgsql_handle_closer(dbh TSRMLS_CC);
! 1088: }
! 1089:
! 1090: return ret;
! 1091: }
! 1092: /* }}} */
! 1093:
! 1094: pdo_driver_t pdo_pgsql_driver = {
! 1095: PDO_DRIVER_HEADER(pgsql),
! 1096: pdo_pgsql_handle_factory
! 1097: };
! 1098:
! 1099: /*
! 1100: * Local variables:
! 1101: * tab-width: 4
! 1102: * c-basic-offset: 4
! 1103: * End:
! 1104: * vim600: noet sw=4 ts=4 fdm=marker
! 1105: * vim<600: noet sw=4 ts=4
! 1106: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>