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