Annotation of embedaddon/php/ext/pdo_pgsql/pgsql_statement.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_statement.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 "php_pdo_pgsql.h"
! 33: #include "php_pdo_pgsql_int.h"
! 34: #if HAVE_NETINET_IN_H
! 35: #include <netinet/in.h>
! 36: #endif
! 37:
! 38: /* from postgresql/src/include/catalog/pg_type.h */
! 39: #define BOOLOID 16
! 40: #define BYTEAOID 17
! 41: #define INT8OID 20
! 42: #define INT2OID 21
! 43: #define INT4OID 23
! 44: #define TEXTOID 25
! 45: #define OIDOID 26
! 46:
! 47: static int pgsql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
! 48: {
! 49: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 50:
! 51: if (S->result) {
! 52: /* free the resource */
! 53: PQclear(S->result);
! 54: S->result = NULL;
! 55: }
! 56:
! 57: #if HAVE_PQPREPARE
! 58: if (S->stmt_name) {
! 59: pdo_pgsql_db_handle *H = S->H;
! 60: char *q = NULL;
! 61: PGresult *res;
! 62:
! 63: if (S->is_prepared) {
! 64: spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name);
! 65: res = PQexec(H->server, q);
! 66: efree(q);
! 67: if (res) {
! 68: PQclear(res);
! 69: }
! 70: }
! 71: efree(S->stmt_name);
! 72: S->stmt_name = NULL;
! 73: }
! 74: if (S->param_lengths) {
! 75: efree(S->param_lengths);
! 76: S->param_lengths = NULL;
! 77: }
! 78: if (S->param_values) {
! 79: efree(S->param_values);
! 80: S->param_values = NULL;
! 81: }
! 82: if (S->param_formats) {
! 83: efree(S->param_formats);
! 84: S->param_formats = NULL;
! 85: }
! 86: if (S->param_types) {
! 87: efree(S->param_types);
! 88: S->param_types = NULL;
! 89: }
! 90: if (S->query) {
! 91: efree(S->query);
! 92: S->query = NULL;
! 93: }
! 94: #endif
! 95:
! 96: if (S->cursor_name) {
! 97: pdo_pgsql_db_handle *H = S->H;
! 98: char *q = NULL;
! 99: PGresult *res;
! 100:
! 101: spprintf(&q, 0, "CLOSE %s", S->cursor_name);
! 102: res = PQexec(H->server, q);
! 103: efree(q);
! 104: if (res) PQclear(res);
! 105: efree(S->cursor_name);
! 106: S->cursor_name = NULL;
! 107: }
! 108:
! 109: if(S->cols) {
! 110: efree(S->cols);
! 111: S->cols = NULL;
! 112: }
! 113: efree(S);
! 114: stmt->driver_data = NULL;
! 115: return 1;
! 116: }
! 117:
! 118: static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
! 119: {
! 120: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 121: pdo_pgsql_db_handle *H = S->H;
! 122: ExecStatusType status;
! 123:
! 124: /* ensure that we free any previous unfetched results */
! 125: if(S->result) {
! 126: PQclear(S->result);
! 127: S->result = NULL;
! 128: }
! 129:
! 130: S->current_row = 0;
! 131:
! 132: if (S->cursor_name) {
! 133: char *q = NULL;
! 134:
! 135: if (S->is_prepared) {
! 136: spprintf(&q, 0, "CLOSE %s", S->cursor_name);
! 137: S->result = PQexec(H->server, q);
! 138: efree(q);
! 139: }
! 140:
! 141: spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, stmt->active_query_string);
! 142: S->result = PQexec(H->server, q);
! 143: efree(q);
! 144:
! 145: /* check if declare failed */
! 146: status = PQresultStatus(S->result);
! 147: if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
! 148: pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
! 149: return 0;
! 150: }
! 151:
! 152: /* the cursor was declared correctly */
! 153: S->is_prepared = 1;
! 154:
! 155: /* fetch to be able to get the number of tuples later, but don't advance the cursor pointer */
! 156: spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name);
! 157: S->result = PQexec(H->server, q);
! 158: efree(q);
! 159: } else
! 160: #if HAVE_PQPREPARE
! 161: if (S->stmt_name) {
! 162: /* using a prepared statement */
! 163:
! 164: if (!S->is_prepared) {
! 165: stmt_retry:
! 166: /* we deferred the prepare until now, because we didn't
! 167: * know anything about the parameter types; now we do */
! 168: S->result = PQprepare(H->server, S->stmt_name, S->query,
! 169: stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
! 170: S->param_types);
! 171: status = PQresultStatus(S->result);
! 172: switch (status) {
! 173: case PGRES_COMMAND_OK:
! 174: case PGRES_TUPLES_OK:
! 175: /* it worked */
! 176: S->is_prepared = 1;
! 177: PQclear(S->result);
! 178: break;
! 179: default: {
! 180: char *sqlstate = pdo_pgsql_sqlstate(S->result);
! 181: /* 42P05 means that the prepared statement already existed. this can happen if you use
! 182: * a connection pooling software line pgpool which doesn't close the db-connection once
! 183: * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no
! 184: * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we
! 185: * deallocate it and retry ONCE (thies 2005.12.15)
! 186: */
! 187: if (sqlstate && !strcmp(sqlstate, "42P05")) {
! 188: char buf[100]; /* stmt_name == "pdo_crsr_%08x" */
! 189: PGresult *res;
! 190: snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
! 191: res = PQexec(H->server, buf);
! 192: if (res) {
! 193: PQclear(res);
! 194: }
! 195: goto stmt_retry;
! 196: } else {
! 197: pdo_pgsql_error_stmt(stmt, status, sqlstate);
! 198: return 0;
! 199: }
! 200: }
! 201: }
! 202: }
! 203: S->result = PQexecPrepared(H->server, S->stmt_name,
! 204: stmt->bound_params ?
! 205: zend_hash_num_elements(stmt->bound_params) :
! 206: 0,
! 207: (const char**)S->param_values,
! 208: S->param_lengths,
! 209: S->param_formats,
! 210: 0);
! 211: } else
! 212: #endif
! 213: {
! 214: S->result = PQexec(H->server, stmt->active_query_string);
! 215: }
! 216: status = PQresultStatus(S->result);
! 217:
! 218: if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
! 219: pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
! 220: return 0;
! 221: }
! 222:
! 223: if (!stmt->executed && !stmt->column_count) {
! 224: stmt->column_count = (int) PQnfields(S->result);
! 225: S->cols = ecalloc(stmt->column_count, sizeof(pdo_pgsql_column));
! 226: }
! 227:
! 228: if (status == PGRES_COMMAND_OK) {
! 229: stmt->row_count = (long)atoi(PQcmdTuples(S->result));
! 230: H->pgoid = PQoidValue(S->result);
! 231: } else {
! 232: stmt->row_count = (long)PQntuples(S->result);
! 233: }
! 234:
! 235: return 1;
! 236: }
! 237:
! 238: static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
! 239: enum pdo_param_event event_type TSRMLS_DC)
! 240: {
! 241: #if HAVE_PQPREPARE
! 242: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 243:
! 244: if (S->stmt_name && param->is_param) {
! 245: switch (event_type) {
! 246: case PDO_PARAM_EVT_FREE:
! 247: if (param->driver_data) {
! 248: efree(param->driver_data);
! 249: }
! 250: break;
! 251:
! 252: case PDO_PARAM_EVT_NORMALIZE:
! 253: /* decode name from $1, $2 into 0, 1 etc. */
! 254: if (param->name) {
! 255: if (param->name[0] == '$') {
! 256: param->paramno = atoi(param->name + 1);
! 257: } else {
! 258: /* resolve parameter name to rewritten name */
! 259: char *nameptr;
! 260: if (stmt->bound_param_map && SUCCESS == zend_hash_find(stmt->bound_param_map,
! 261: param->name, param->namelen + 1, (void**)&nameptr)) {
! 262: param->paramno = atoi(nameptr + 1) - 1;
! 263: } else {
! 264: pdo_raise_impl_error(stmt->dbh, stmt, "HY093", param->name TSRMLS_CC);
! 265: return 0;
! 266: }
! 267: }
! 268: }
! 269: break;
! 270:
! 271: case PDO_PARAM_EVT_ALLOC:
! 272: case PDO_PARAM_EVT_EXEC_POST:
! 273: case PDO_PARAM_EVT_FETCH_PRE:
! 274: case PDO_PARAM_EVT_FETCH_POST:
! 275: /* work is handled by EVT_NORMALIZE */
! 276: return 1;
! 277:
! 278: case PDO_PARAM_EVT_EXEC_PRE:
! 279: if (!stmt->bound_param_map) {
! 280: return 0;
! 281: }
! 282: if (!S->param_values) {
! 283: S->param_values = ecalloc(
! 284: zend_hash_num_elements(stmt->bound_param_map),
! 285: sizeof(char*));
! 286: S->param_lengths = ecalloc(
! 287: zend_hash_num_elements(stmt->bound_param_map),
! 288: sizeof(int));
! 289: S->param_formats = ecalloc(
! 290: zend_hash_num_elements(stmt->bound_param_map),
! 291: sizeof(int));
! 292: S->param_types = ecalloc(
! 293: zend_hash_num_elements(stmt->bound_param_map),
! 294: sizeof(Oid));
! 295: }
! 296: if (param->paramno >= 0) {
! 297: if (param->paramno > zend_hash_num_elements(stmt->bound_param_map)) {
! 298: pdo_pgsql_error_stmt(stmt, PGRES_FATAL_ERROR, "HY105");
! 299: return 0;
! 300: }
! 301:
! 302: if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB &&
! 303: Z_TYPE_P(param->parameter) == IS_RESOURCE) {
! 304: php_stream *stm;
! 305: php_stream_from_zval_no_verify(stm, ¶m->parameter);
! 306: if (stm) {
! 307: if (php_stream_is(stm, &pdo_pgsql_lob_stream_ops)) {
! 308: struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stm->abstract;
! 309: pdo_pgsql_bound_param *P = param->driver_data;
! 310:
! 311: if (P == NULL) {
! 312: P = ecalloc(1, sizeof(*P));
! 313: param->driver_data = P;
! 314: }
! 315: P->oid = htonl(self->oid);
! 316: S->param_values[param->paramno] = (char*)&P->oid;
! 317: S->param_lengths[param->paramno] = sizeof(P->oid);
! 318: S->param_formats[param->paramno] = 1;
! 319: S->param_types[param->paramno] = OIDOID;
! 320: return 1;
! 321: } else {
! 322: int len;
! 323:
! 324: SEPARATE_ZVAL_IF_NOT_REF(¶m->parameter);
! 325: Z_TYPE_P(param->parameter) = IS_STRING;
! 326:
! 327: if ((len = php_stream_copy_to_mem(stm, &Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0)) > 0) {
! 328: Z_STRLEN_P(param->parameter) = len;
! 329: } else {
! 330: ZVAL_EMPTY_STRING(param->parameter);
! 331: }
! 332: }
! 333: } else {
! 334: /* expected a stream resource */
! 335: pdo_pgsql_error_stmt(stmt, PGRES_FATAL_ERROR, "HY105");
! 336: return 0;
! 337: }
! 338: }
! 339:
! 340: if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL ||
! 341: Z_TYPE_P(param->parameter) == IS_NULL) {
! 342: S->param_values[param->paramno] = NULL;
! 343: S->param_lengths[param->paramno] = 0;
! 344: } else if (Z_TYPE_P(param->parameter) == IS_BOOL) {
! 345: S->param_values[param->paramno] = Z_BVAL_P(param->parameter) ? "t" : "f";
! 346: S->param_lengths[param->paramno] = 1;
! 347: S->param_formats[param->paramno] = 0;
! 348: } else {
! 349: SEPARATE_ZVAL_IF_NOT_REF(¶m->parameter);
! 350: convert_to_string(param->parameter);
! 351: S->param_values[param->paramno] = Z_STRVAL_P(param->parameter);
! 352: S->param_lengths[param->paramno] = Z_STRLEN_P(param->parameter);
! 353: S->param_formats[param->paramno] = 0;
! 354: }
! 355:
! 356: if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
! 357: S->param_types[param->paramno] = 0;
! 358: S->param_formats[param->paramno] = 1;
! 359: } else {
! 360: S->param_types[param->paramno] = 0;
! 361: }
! 362: }
! 363: break;
! 364: }
! 365: }
! 366: #endif
! 367: return 1;
! 368: }
! 369:
! 370: static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
! 371: enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
! 372: {
! 373: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 374:
! 375: if (S->cursor_name) {
! 376: char *ori_str = NULL;
! 377: char *q = NULL;
! 378: ExecStatusType status;
! 379:
! 380: switch (ori) {
! 381: case PDO_FETCH_ORI_NEXT: spprintf(&ori_str, 0, "NEXT"); break;
! 382: case PDO_FETCH_ORI_PRIOR: spprintf(&ori_str, 0, "BACKWARD"); break;
! 383: case PDO_FETCH_ORI_FIRST: spprintf(&ori_str, 0, "FIRST"); break;
! 384: case PDO_FETCH_ORI_LAST: spprintf(&ori_str, 0, "LAST"); break;
! 385: case PDO_FETCH_ORI_ABS: spprintf(&ori_str, 0, "ABSOLUTE %ld", offset); break;
! 386: case PDO_FETCH_ORI_REL: spprintf(&ori_str, 0, "RELATIVE %ld", offset); break;
! 387: default:
! 388: return 0;
! 389: }
! 390:
! 391: spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name);
! 392: efree(ori_str);
! 393: S->result = PQexec(S->H->server, q);
! 394: efree(q);
! 395: status = PQresultStatus(S->result);
! 396:
! 397: if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
! 398: pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
! 399: return 0;
! 400: }
! 401:
! 402: if (PQntuples(S->result)) {
! 403: S->current_row = 1;
! 404: return 1;
! 405: } else {
! 406: return 0;
! 407: }
! 408: } else {
! 409: if (S->current_row < stmt->row_count) {
! 410: S->current_row++;
! 411: return 1;
! 412: } else {
! 413: return 0;
! 414: }
! 415: }
! 416: }
! 417:
! 418: static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
! 419: {
! 420: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 421: struct pdo_column_data *cols = stmt->columns;
! 422: struct pdo_bound_param_data *param;
! 423:
! 424: if (!S->result) {
! 425: return 0;
! 426: }
! 427:
! 428: cols[colno].name = estrdup(PQfname(S->result, colno));
! 429: cols[colno].namelen = strlen(cols[colno].name);
! 430: cols[colno].maxlen = PQfsize(S->result, colno);
! 431: cols[colno].precision = PQfmod(S->result, colno);
! 432: S->cols[colno].pgsql_type = PQftype(S->result, colno);
! 433:
! 434: switch(S->cols[colno].pgsql_type) {
! 435:
! 436: case BOOLOID:
! 437: cols[colno].param_type = PDO_PARAM_BOOL;
! 438: break;
! 439:
! 440: case OIDOID:
! 441: /* did the user bind the column as a LOB ? */
! 442: if (stmt->bound_columns && (
! 443: SUCCESS == zend_hash_index_find(stmt->bound_columns,
! 444: colno, (void**)¶m) ||
! 445: SUCCESS == zend_hash_find(stmt->bound_columns,
! 446: cols[colno].name, cols[colno].namelen,
! 447: (void**)¶m))) {
! 448: if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
! 449: cols[colno].param_type = PDO_PARAM_LOB;
! 450: break;
! 451: }
! 452: }
! 453: cols[colno].param_type = PDO_PARAM_INT;
! 454: break;
! 455:
! 456: case INT2OID:
! 457: case INT4OID:
! 458: cols[colno].param_type = PDO_PARAM_INT;
! 459: break;
! 460:
! 461: case INT8OID:
! 462: if (sizeof(long)>=8) {
! 463: cols[colno].param_type = PDO_PARAM_INT;
! 464: } else {
! 465: cols[colno].param_type = PDO_PARAM_STR;
! 466: }
! 467: break;
! 468:
! 469: case BYTEAOID:
! 470: cols[colno].param_type = PDO_PARAM_LOB;
! 471: break;
! 472:
! 473: default:
! 474: cols[colno].param_type = PDO_PARAM_STR;
! 475: }
! 476:
! 477: return 1;
! 478: }
! 479:
! 480: static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
! 481: {
! 482: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 483: struct pdo_column_data *cols = stmt->columns;
! 484: size_t tmp_len;
! 485:
! 486: if (!S->result) {
! 487: return 0;
! 488: }
! 489:
! 490: /* We have already increased count by 1 in pgsql_stmt_fetch() */
! 491: if (PQgetisnull(S->result, S->current_row - 1, colno)) { /* Check if we got NULL */
! 492: *ptr = NULL;
! 493: *len = 0;
! 494: } else {
! 495: *ptr = PQgetvalue(S->result, S->current_row - 1, colno);
! 496: *len = PQgetlength(S->result, S->current_row - 1, colno);
! 497:
! 498: switch(cols[colno].param_type) {
! 499:
! 500: case PDO_PARAM_INT:
! 501: S->cols[colno].intval = atol(*ptr);
! 502: *ptr = (char *) &(S->cols[colno].intval);
! 503: *len = sizeof(long);
! 504: break;
! 505:
! 506: case PDO_PARAM_BOOL:
! 507: S->cols[colno].boolval = **ptr == 't' ? 1: 0;
! 508: *ptr = (char *) &(S->cols[colno].boolval);
! 509: *len = sizeof(zend_bool);
! 510: break;
! 511:
! 512: case PDO_PARAM_LOB:
! 513: if (S->cols[colno].pgsql_type == OIDOID) {
! 514: /* ooo, a real large object */
! 515: char *end_ptr;
! 516: Oid oid = (Oid)strtoul(*ptr, &end_ptr, 10);
! 517: int loid = lo_open(S->H->server, oid, INV_READ);
! 518: if (loid >= 0) {
! 519: *ptr = (char*)pdo_pgsql_create_lob_stream(stmt->dbh, loid, oid TSRMLS_CC);
! 520: *len = 0;
! 521: return *ptr ? 1 : 0;
! 522: }
! 523: *ptr = NULL;
! 524: *len = 0;
! 525: return 0;
! 526: } else {
! 527: char *tmp_ptr = PQunescapeBytea(*ptr, &tmp_len);
! 528: if (!tmp_ptr) {
! 529: /* PQunescapeBytea returned an error */
! 530: *len = 0;
! 531: return 0;
! 532: }
! 533: if (!tmp_len) {
! 534: /* Empty string, return as empty stream */
! 535: *ptr = (char *)php_stream_memory_open(TEMP_STREAM_READONLY, "", 0);
! 536: PQfreemem(tmp_ptr);
! 537: *len = 0;
! 538: } else {
! 539: *ptr = estrndup(tmp_ptr, tmp_len);
! 540: PQfreemem(tmp_ptr);
! 541: *len = tmp_len;
! 542: *caller_frees = 1;
! 543: }
! 544: }
! 545: break;
! 546: case PDO_PARAM_NULL:
! 547: case PDO_PARAM_STR:
! 548: case PDO_PARAM_STMT:
! 549: case PDO_PARAM_INPUT_OUTPUT:
! 550: case PDO_PARAM_ZVAL:
! 551: default:
! 552: break;
! 553: }
! 554: }
! 555:
! 556: return 1;
! 557: }
! 558:
! 559: static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
! 560: {
! 561: pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
! 562: PGresult *res;
! 563: char *q=NULL;
! 564: ExecStatusType status;
! 565:
! 566: if (!S->result) {
! 567: return FAILURE;
! 568: }
! 569:
! 570: if (colno >= stmt->column_count) {
! 571: return FAILURE;
! 572: }
! 573:
! 574: array_init(return_value);
! 575: add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type);
! 576:
! 577: /* Fetch metadata from Postgres system catalogue */
! 578: spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%d", S->cols[colno].pgsql_type);
! 579: res = PQexec(S->H->server, q);
! 580: efree(q);
! 581:
! 582: status = PQresultStatus(res);
! 583:
! 584: if (status != PGRES_TUPLES_OK) {
! 585: /* Failed to get system catalogue, but return success
! 586: * with the data we have collected so far
! 587: */
! 588: goto done;
! 589: }
! 590:
! 591: /* We want exactly one row returned */
! 592: if (1 != PQntuples(res)) {
! 593: goto done;
! 594: }
! 595:
! 596: add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0), 1);
! 597: done:
! 598: PQclear(res);
! 599: return 1;
! 600: }
! 601:
! 602: static int pdo_pgsql_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
! 603: {
! 604: return 1;
! 605: }
! 606:
! 607: struct pdo_stmt_methods pgsql_stmt_methods = {
! 608: pgsql_stmt_dtor,
! 609: pgsql_stmt_execute,
! 610: pgsql_stmt_fetch,
! 611: pgsql_stmt_describe,
! 612: pgsql_stmt_get_col,
! 613: pgsql_stmt_param_hook,
! 614: NULL, /* set_attr */
! 615: NULL, /* get_attr */
! 616: pgsql_stmt_get_column_meta,
! 617: NULL, /* next_rowset */
! 618: pdo_pgsql_stmt_cursor_closer
! 619: };
! 620:
! 621: /*
! 622: * Local variables:
! 623: * tab-width: 4
! 624: * c-basic-offset: 4
! 625: * End:
! 626: * vim600: noet sw=4 ts=4 fdm=marker
! 627: * vim<600: noet sw=4 ts=4
! 628: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>