PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pdo_pgsql - pgsql_statement.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 363 398 91.2 %
Date: 2022-01-16 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2018 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 "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 BOOLLABEL   "bool"
      40             : #define BOOLOID     16
      41             : #define BYTEALABEL  "bytea"
      42             : #define BYTEAOID    17
      43             : #define DATELABEL   "date"
      44             : #define DATEOID     1082
      45             : #define INT2LABEL   "int2"
      46             : #define INT2OID     21
      47             : #define INT4LABEL   "int4"
      48             : #define INT4OID     23
      49             : #define INT8LABEL   "int8"
      50             : #define INT8OID     20
      51             : #define OIDOID      26
      52             : #define TEXTLABEL   "text"
      53             : #define TEXTOID     25
      54             : #define TIMESTAMPLABEL "timestamp"
      55             : #define TIMESTAMPOID   1114
      56             : #define VARCHARLABEL "varchar"
      57             : #define VARCHAROID   1043
      58             : 
      59             : 
      60             : 
      61         506 : static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
      62             : {
      63         506 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
      64        1518 :         zend_bool server_obj_usable = !Z_ISUNDEF(stmt->database_object_handle)
      65         490 :                 && IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)])
      66         996 :                 && !(GC_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED);
      67             : 
      68         506 :         if (S->result) {
      69             :                 /* free the resource */
      70         492 :                 PQclear(S->result);
      71         492 :                 S->result = NULL;
      72             :         }
      73             : 
      74         506 :         if (S->stmt_name) {
      75         488 :                 if (S->is_prepared && server_obj_usable) {
      76         461 :                         pdo_pgsql_db_handle *H = S->H;
      77         461 :                         char *q = NULL;
      78             :                         PGresult *res;
      79             : 
      80         461 :                         spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name);
      81         461 :                         res = PQexec(H->server, q);
      82         461 :                         efree(q);
      83         461 :                         if (res) {
      84         461 :                                 PQclear(res);
      85             :                         }
      86             :                 }
      87         488 :                 efree(S->stmt_name);
      88         488 :                 S->stmt_name = NULL;
      89             :         }
      90         506 :         if (S->param_lengths) {
      91          46 :                 efree(S->param_lengths);
      92          46 :                 S->param_lengths = NULL;
      93             :         }
      94         506 :         if (S->param_values) {
      95          46 :                 efree(S->param_values);
      96          46 :                 S->param_values = NULL;
      97             :         }
      98         506 :         if (S->param_formats) {
      99          46 :                 efree(S->param_formats);
     100          46 :                 S->param_formats = NULL;
     101             :         }
     102         506 :         if (S->param_types) {
     103          46 :                 efree(S->param_types);
     104          46 :                 S->param_types = NULL;
     105             :         }
     106         506 :         if (S->query) {
     107         489 :                 efree(S->query);
     108         489 :                 S->query = NULL;
     109             :         }
     110             : 
     111         506 :         if (S->cursor_name) {
     112           4 :                 if (server_obj_usable) {
     113           4 :                         pdo_pgsql_db_handle *H = S->H;
     114           4 :                         char *q = NULL;
     115             :                         PGresult *res;
     116             : 
     117           4 :                         spprintf(&q, 0, "CLOSE %s", S->cursor_name);
     118           4 :                         res = PQexec(H->server, q);
     119           4 :                         efree(q);
     120           4 :                         if (res) PQclear(res);
     121             :                 }
     122           4 :                 efree(S->cursor_name);
     123           4 :                 S->cursor_name = NULL;
     124             :         }
     125             : 
     126         506 :         if(S->cols) {
     127         462 :                 efree(S->cols);
     128         462 :                 S->cols = NULL;
     129             :         }
     130         506 :         efree(S);
     131         506 :         stmt->driver_data = NULL;
     132         506 :         return 1;
     133             : }
     134             : 
     135        1590 : static int pgsql_stmt_execute(pdo_stmt_t *stmt)
     136             : {
     137        1590 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     138        1590 :         pdo_pgsql_db_handle *H = S->H;
     139             :         ExecStatusType status;
     140             : 
     141             :         /* ensure that we free any previous unfetched results */
     142        1590 :         if(S->result) {
     143        1098 :                 PQclear(S->result);
     144        1098 :                 S->result = NULL;
     145             :         }
     146             : 
     147        1590 :         S->current_row = 0;
     148             : 
     149        1590 :         if (S->cursor_name) {
     150           5 :                 char *q = NULL;
     151             : 
     152           5 :                 if (S->is_prepared) {
     153           1 :                         spprintf(&q, 0, "CLOSE %s", S->cursor_name);
     154           1 :                         S->result = PQexec(H->server, q);
     155           1 :                         efree(q);
     156             :                 }
     157             : 
     158           5 :                 spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, stmt->active_query_string);
     159           5 :                 S->result = PQexec(H->server, q);
     160           5 :                 efree(q);
     161             : 
     162             :                 /* check if declare failed */
     163           5 :                 status = PQresultStatus(S->result);
     164           5 :                 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
     165           1 :                         pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
     166           1 :                         return 0;
     167             :                 }
     168           4 :                 PQclear(S->result);
     169             : 
     170             :                 /* the cursor was declared correctly */
     171           4 :                 S->is_prepared = 1;
     172             : 
     173             :                 /* fetch to be able to get the number of tuples later, but don't advance the cursor pointer */
     174           4 :                 spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name);
     175           4 :                 S->result = PQexec(H->server, q);
     176           4 :                 efree(q);
     177        1585 :         } else if (S->stmt_name) {
     178             :                 /* using a prepared statement */
     179             : 
     180        1564 :                 if (!S->is_prepared) {
     181         477 : stmt_retry:
     182             :                         /* we deferred the prepare until now, because we didn't
     183             :                          * know anything about the parameter types; now we do */
     184         524 :                         S->result = PQprepare(H->server, S->stmt_name, S->query,
     185         524 :                                                 stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
     186         477 :                                                 S->param_types);
     187         477 :                         status = PQresultStatus(S->result);
     188         477 :                         switch (status) {
     189         467 :                                 case PGRES_COMMAND_OK:
     190             :                                 case PGRES_TUPLES_OK:
     191             :                                         /* it worked */
     192         467 :                                         S->is_prepared = 1;
     193         467 :                                         PQclear(S->result);
     194         467 :                                         break;
     195          10 :                                 default: {
     196          10 :                                         char *sqlstate = pdo_pgsql_sqlstate(S->result);
     197             :                                         /* 42P05 means that the prepared statement already existed. this can happen if you use
     198             :                                          * a connection pooling software line pgpool which doesn't close the db-connection once
     199             :                                          * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no
     200             :                                          * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we
     201             :                                          * deallocate it and retry ONCE (thies 2005.12.15)
     202             :                                          */
     203          10 :                                         if (sqlstate && !strcmp(sqlstate, "42P05")) {
     204             :                                                 char buf[100]; /* stmt_name == "pdo_crsr_%08x" */
     205             :                                                 PGresult *res;
     206           0 :                                                 snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
     207           0 :                                                 res = PQexec(H->server, buf);
     208           0 :                                                 if (res) {
     209           0 :                                                         PQclear(res);
     210             :                                                 }
     211           0 :                                                 goto stmt_retry;
     212             :                                         } else {
     213          10 :                                                 pdo_pgsql_error_stmt(stmt, status, sqlstate);
     214          10 :                                                 return 0;
     215             :                                         }
     216             :                                 }
     217             :                         }
     218        1087 :                 }
     219        2658 :                 S->result = PQexecPrepared(H->server, S->stmt_name,
     220        1554 :                                 stmt->bound_params ?
     221        1104 :                                         zend_hash_num_elements(stmt->bound_params) :
     222             :                                         0,
     223        1554 :                                 (const char**)S->param_values,
     224        1554 :                                 S->param_lengths,
     225        1554 :                                 S->param_formats,
     226             :                                 0);
     227          21 :         } else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) {
     228             :                 /* execute query with parameters */
     229           4 :                 S->result = PQexecParams(H->server, S->query,
     230           4 :                                 stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
     231           2 :                                 S->param_types,
     232           2 :                                 (const char**)S->param_values,
     233           2 :                                 S->param_lengths,
     234           2 :                                 S->param_formats,
     235             :                                 0);
     236             :         } else {
     237             :                 /* execute plain query (with embedded parameters) */
     238          19 :                 S->result = PQexec(H->server, stmt->active_query_string);
     239             :         }
     240        1579 :         status = PQresultStatus(S->result);
     241             : 
     242        1579 :         if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
     243          12 :                 pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
     244          12 :                 return 0;
     245             :         }
     246             : 
     247        1567 :         if (!stmt->executed && (!stmt->column_count || S->cols == NULL)) {
     248        1490 :                 stmt->column_count = (int) PQnfields(S->result);
     249        1490 :                 S->cols = ecalloc(stmt->column_count, sizeof(pdo_pgsql_column));
     250             :         }
     251             : 
     252        1567 :         if (status == PGRES_COMMAND_OK) {
     253        1083 :                 ZEND_ATOL(stmt->row_count, PQcmdTuples(S->result));
     254        1083 :                 H->pgoid = PQoidValue(S->result);
     255             :         } else {
     256         484 :                 stmt->row_count = (zend_long)PQntuples(S->result);
     257             :         }
     258             : 
     259        1567 :         return 1;
     260             : }
     261             : 
     262       23485 : static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
     263             :                 enum pdo_param_event event_type)
     264             : {
     265       23485 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     266             : 
     267       23485 :         if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED && param->is_param) {
     268       22088 :                 switch (event_type) {
     269        4523 :                         case PDO_PARAM_EVT_FREE:
     270        4523 :                                 if (param->driver_data) {
     271           1 :                                         efree(param->driver_data);
     272             :                                 }
     273        4523 :                                 break;
     274             : 
     275        4525 :                         case PDO_PARAM_EVT_NORMALIZE:
     276             :                                 /* decode name from $1, $2 into 0, 1 etc. */
     277        4525 :                                 if (param->name) {
     278        4067 :                                         if (ZSTR_VAL(param->name)[0] == '$') {
     279           0 :                                                 ZEND_ATOL(param->paramno, ZSTR_VAL(param->name) + 1);
     280             :                                         } else {
     281             :                                                 /* resolve parameter name to rewritten name */
     282             :                                                 char *namevar;
     283             : 
     284        8133 :                                                 if (stmt->bound_param_map && (namevar = zend_hash_find_ptr(stmt->bound_param_map,
     285             :                                                                 param->name)) != NULL) {
     286        4065 :                                                         ZEND_ATOL(param->paramno, namevar + 1);
     287        4065 :                                                         param->paramno--;
     288             :                                                 } else {
     289           2 :                                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY093", ZSTR_VAL(param->name));
     290           2 :                                                         return 0;
     291             :                                                 }
     292             :                                         }
     293             :                                 }
     294        4523 :                                 break;
     295             : 
     296        4523 :                         case PDO_PARAM_EVT_ALLOC:
     297        4523 :                                 if (!stmt->bound_param_map) {
     298           2 :                                         return 1;
     299             :                                 }
     300        4521 :                                 if (!zend_hash_index_exists(stmt->bound_param_map, param->paramno)) {
     301           4 :                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
     302           4 :                                         return 0;
     303             :                                 }
     304             :                         case PDO_PARAM_EVT_EXEC_POST:
     305             :                         case PDO_PARAM_EVT_FETCH_PRE:
     306             :                         case PDO_PARAM_EVT_FETCH_POST:
     307             :                                 /* work is handled by EVT_NORMALIZE */
     308        8827 :                                 return 1;
     309             : 
     310        4207 :                         case PDO_PARAM_EVT_EXEC_PRE:
     311        4207 :                                 if (!stmt->bound_param_map) {
     312           2 :                                         return 1;
     313             :                                 }
     314        4205 :                                 if (!S->param_values) {
     315          46 :                                         S->param_values = ecalloc(
     316             :                                                         zend_hash_num_elements(stmt->bound_param_map),
     317             :                                                         sizeof(char*));
     318          46 :                                         S->param_lengths = ecalloc(
     319             :                                                         zend_hash_num_elements(stmt->bound_param_map),
     320             :                                                         sizeof(int));
     321          46 :                                         S->param_formats = ecalloc(
     322             :                                                         zend_hash_num_elements(stmt->bound_param_map),
     323             :                                                         sizeof(int));
     324          46 :                                         S->param_types = ecalloc(
     325             :                                                         zend_hash_num_elements(stmt->bound_param_map),
     326             :                                                         sizeof(Oid));
     327             :                                 }
     328        4205 :                                 if (param->paramno >= 0) {
     329             :                                         zval *parameter;
     330             : 
     331             :                                         /*
     332             :                                         if (param->paramno >= zend_hash_num_elements(stmt->bound_params)) {
     333             :                                                 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
     334             :                                                 return 0;
     335             :                                         }
     336             :                                         */
     337             : 
     338        8410 :                                         if (Z_ISREF(param->parameter)) {
     339          50 :                                                 parameter = Z_REFVAL(param->parameter);
     340             :                                         } else {
     341        4155 :                                                 parameter = &param->parameter;
     342             :                                         }
     343             : 
     344        4215 :                                         if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB &&
     345          10 :                                                         Z_TYPE_P(parameter) == IS_RESOURCE) {
     346             :                                                 php_stream *stm;
     347           6 :                                                 php_stream_from_zval_no_verify(stm, parameter);
     348           6 :                                                 if (stm) {
     349           6 :                                                         if (php_stream_is(stm, &pdo_pgsql_lob_stream_ops)) {
     350           1 :                                                                 struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stm->abstract;
     351           1 :                                                                 pdo_pgsql_bound_param *P = param->driver_data;
     352             : 
     353           1 :                                                                 if (P == NULL) {
     354           1 :                                                                         P = ecalloc(1, sizeof(*P));
     355           1 :                                                                         param->driver_data = P;
     356             :                                                                 }
     357           1 :                                                                 P->oid = htonl(self->oid);
     358           1 :                                                                 S->param_values[param->paramno] = (char*)&P->oid;
     359           1 :                                                                 S->param_lengths[param->paramno] = sizeof(P->oid);
     360           1 :                                                                 S->param_formats[param->paramno] = 1;
     361           1 :                                                                 S->param_types[param->paramno] = OIDOID;
     362           1 :                                                                 return 1;
     363             :                                                         } else {
     364           5 :                                                                 zend_string *str = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
     365           5 :                                                                 if (str != NULL) {
     366             :                                                                         //??SEPARATE_ZVAL_IF_NOT_REF(&param->parameter);
     367           3 :                                                                         ZVAL_STR(parameter, str);
     368             :                                                                 } else {
     369           2 :                                                                         ZVAL_EMPTY_STRING(parameter);
     370             :                                                                 }
     371             :                                                         }
     372             :                                                 } else {
     373             :                                                         /* expected a stream resource */
     374           0 :                                                         pdo_pgsql_error_stmt(stmt, PGRES_FATAL_ERROR, "HY105");
     375           0 :                                                         return 0;
     376             :                                                 }
     377             :                                         }
     378             : 
     379        8408 :                                         if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL ||
     380        4204 :                                                         Z_TYPE_P(parameter) == IS_NULL) {
     381           7 :                                                 S->param_values[param->paramno] = NULL;
     382           7 :                                                 S->param_lengths[param->paramno] = 0;
     383        8393 :                                         } else if (Z_TYPE_P(parameter) == IS_FALSE || Z_TYPE_P(parameter) == IS_TRUE) {
     384           2 :                                                 S->param_values[param->paramno] = Z_TYPE_P(parameter) == IS_TRUE ? "t" : "f";
     385           2 :                                                 S->param_lengths[param->paramno] = 1;
     386           2 :                                                 S->param_formats[param->paramno] = 0;
     387             :                                         } else {
     388             :                                                 //SEPARATE_ZVAL_IF_NOT_REF(&param->parameter);
     389        4217 :                                                 convert_to_string_ex(parameter);
     390        4195 :                                                 S->param_values[param->paramno] = Z_STRVAL_P(parameter);
     391        4195 :                                                 S->param_lengths[param->paramno] = Z_STRLEN_P(parameter);
     392        4195 :                                                 S->param_formats[param->paramno] = 0;
     393             :                                         }
     394             : 
     395        4204 :                                         if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
     396           9 :                                                 S->param_types[param->paramno] = 0;
     397           9 :                                                 S->param_formats[param->paramno] = 1;
     398             :                                         } else {
     399        4195 :                                                 S->param_types[param->paramno] = 0;
     400             :                                         }
     401             :                                 }
     402        4204 :                                 break;
     403             :                 }
     404       13250 :         } else if (param->is_param) {
     405             :                 /* We need to manually convert to a pg native boolean value */
     406        1129 :                 if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL &&
     407           7 :                         ((param->param_type & PDO_PARAM_INPUT_OUTPUT) != PDO_PARAM_INPUT_OUTPUT)) {
     408           7 :                         const char *s = zend_is_true(&param->parameter) ? "t" : "f";
     409           7 :                         param->param_type = PDO_PARAM_STR;
     410           7 :                         zval_ptr_dtor(&param->parameter);
     411          14 :                         ZVAL_STRINGL(&param->parameter, s, 1);
     412             :                 }
     413             :         }
     414       14647 :         return 1;
     415             : }
     416             : 
     417         430 : static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
     418             :         enum pdo_fetch_orientation ori, zend_long offset)
     419             : {
     420         430 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     421             : 
     422         430 :         if (S->cursor_name) {
     423          16 :                 char *ori_str = NULL;
     424          16 :                 char *q = NULL;
     425             :                 ExecStatusType status;
     426             : 
     427          16 :                 switch (ori) {
     428          11 :                         case PDO_FETCH_ORI_NEXT:        spprintf(&ori_str, 0, "NEXT"); break;
     429           1 :                         case PDO_FETCH_ORI_PRIOR:       spprintf(&ori_str, 0, "BACKWARD"); break;
     430           1 :                         case PDO_FETCH_ORI_FIRST:       spprintf(&ori_str, 0, "FIRST"); break;
     431           1 :                         case PDO_FETCH_ORI_LAST:        spprintf(&ori_str, 0, "LAST"); break;
     432           1 :                         case PDO_FETCH_ORI_ABS:         spprintf(&ori_str, 0, "ABSOLUTE " ZEND_LONG_FMT, offset); break;
     433           1 :                         case PDO_FETCH_ORI_REL:         spprintf(&ori_str, 0, "RELATIVE " ZEND_LONG_FMT, offset); break;
     434           0 :                         default:
     435           0 :                                 return 0;
     436             :                 }
     437             : 
     438          16 :                 if(S->result) {
     439          16 :                         PQclear(S->result);
     440          16 :                         S->result = NULL;
     441             :                 }
     442             : 
     443          16 :                 spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name);
     444          16 :                 efree(ori_str);
     445          16 :                 S->result = PQexec(S->H->server, q);
     446          16 :                 efree(q);
     447          16 :                 status = PQresultStatus(S->result);
     448             : 
     449          16 :                 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
     450           0 :                         pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
     451           0 :                         return 0;
     452             :                 }
     453             : 
     454          16 :                 if (PQntuples(S->result)) {
     455          12 :                         S->current_row = 1;
     456          12 :                         return 1;
     457             :                 } else {
     458           4 :                         return 0;
     459             :                 }
     460             :         } else {
     461         414 :                 if (S->current_row < stmt->row_count) {
     462         316 :                         S->current_row++;
     463         316 :                         return 1;
     464             :                 } else {
     465          98 :                         return 0;
     466             :                 }
     467             :         }
     468             : }
     469             : 
     470         530 : static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno)
     471             : {
     472         530 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     473         530 :         struct pdo_column_data *cols = stmt->columns;
     474             :         struct pdo_bound_param_data *param;
     475             :         char *str;
     476             : 
     477         530 :         if (!S->result) {
     478           0 :                 return 0;
     479             :         }
     480             : 
     481         530 :         str = PQfname(S->result, colno);
     482        1060 :         cols[colno].name = zend_string_init(str, strlen(str), 0);
     483         530 :         cols[colno].maxlen = PQfsize(S->result, colno);
     484         530 :         cols[colno].precision = PQfmod(S->result, colno);
     485         530 :         S->cols[colno].pgsql_type = PQftype(S->result, colno);
     486             : 
     487         530 :         switch (S->cols[colno].pgsql_type) {
     488             : 
     489           3 :                 case BOOLOID:
     490           3 :                         cols[colno].param_type = PDO_PARAM_BOOL;
     491           3 :                         break;
     492             : 
     493           3 :                 case OIDOID:
     494             :                         /* did the user bind the column as a LOB ? */
     495           4 :                         if (stmt->bound_columns && (
     496           2 :                                         (param = zend_hash_index_find_ptr(stmt->bound_columns, colno)) != NULL ||
     497           1 :                                         (param = zend_hash_find_ptr(stmt->bound_columns, cols[colno].name)) != NULL)) {
     498             : 
     499           1 :                                 if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
     500           1 :                                         cols[colno].param_type = PDO_PARAM_LOB;
     501           1 :                                         break;
     502             :                                 }
     503             :                         }
     504           2 :                         cols[colno].param_type = PDO_PARAM_INT;
     505           2 :                         break;
     506             : 
     507         378 :                 case INT2OID:
     508             :                 case INT4OID:
     509         378 :                         cols[colno].param_type = PDO_PARAM_INT;
     510         378 :                         break;
     511             : 
     512          13 :                 case INT8OID:
     513             :                         if (sizeof(zend_long)>=8) {
     514          13 :                                 cols[colno].param_type = PDO_PARAM_INT;
     515             :                         } else {
     516             :                                 cols[colno].param_type = PDO_PARAM_STR;
     517             :                         }
     518          13 :                         break;
     519             : 
     520           3 :                 case BYTEAOID:
     521           3 :                         cols[colno].param_type = PDO_PARAM_LOB;
     522           3 :                         break;
     523             : 
     524         130 :                 default:
     525         130 :                         cols[colno].param_type = PDO_PARAM_STR;
     526             :         }
     527             : 
     528         530 :         return 1;
     529             : }
     530             : 
     531         635 : static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees )
     532             : {
     533         635 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     534         635 :         struct pdo_column_data *cols = stmt->columns;
     535             :         size_t tmp_len;
     536             : 
     537         635 :         if (!S->result) {
     538           0 :                 return 0;
     539             :         }
     540             : 
     541             :         /* We have already increased count by 1 in pgsql_stmt_fetch() */
     542         635 :         if (PQgetisnull(S->result, S->current_row - 1, colno)) { /* Check if we got NULL */
     543          35 :                 *ptr = NULL;
     544          35 :                 *len = 0;
     545             :         } else {
     546         600 :                 *ptr = PQgetvalue(S->result, S->current_row - 1, colno);
     547         600 :                 *len = PQgetlength(S->result, S->current_row - 1, colno);
     548             : 
     549         600 :                 switch (cols[colno].param_type) {
     550             : 
     551         236 :                         case PDO_PARAM_INT:
     552         236 :                                 ZEND_ATOL(S->cols[colno].intval, *ptr);
     553         236 :                                 *ptr = (char *) &(S->cols[colno].intval);
     554         236 :                                 *len = sizeof(zend_long);
     555         236 :                                 break;
     556             : 
     557           2 :                         case PDO_PARAM_BOOL:
     558           2 :                                 S->cols[colno].boolval = **ptr == 't' ? 1: 0;
     559           2 :                                 *ptr = (char *) &(S->cols[colno].boolval);
     560           2 :                                 *len = sizeof(zend_bool);
     561           2 :                                 break;
     562             : 
     563           8 :                         case PDO_PARAM_LOB:
     564           8 :                                 if (S->cols[colno].pgsql_type == OIDOID) {
     565             :                                         /* ooo, a real large object */
     566             :                                         char *end_ptr;
     567           2 :                                         Oid oid = (Oid)strtoul(*ptr, &end_ptr, 10);
     568           2 :                                         int loid = lo_open(S->H->server, oid, INV_READ);
     569           2 :                                         if (loid >= 0) {
     570           2 :                                                 *ptr = (char*)pdo_pgsql_create_lob_stream(&stmt->database_object_handle, loid, oid);
     571           2 :                                                 *len = 0;
     572           2 :                                                 return *ptr ? 1 : 0;
     573             :                                         }
     574           0 :                                         *ptr = NULL;
     575           0 :                                         *len = 0;
     576           0 :                                         return 0;
     577             :                                 } else {
     578           6 :                                         char *tmp_ptr = (char *)PQunescapeBytea((unsigned char *)*ptr, &tmp_len);
     579           6 :                                         if (!tmp_ptr) {
     580             :                                                 /* PQunescapeBytea returned an error */
     581           0 :                                                 *len = 0;
     582           0 :                                                 return 0;
     583             :                                         }
     584           6 :                                         if (!tmp_len) {
     585             :                                                 /* Empty string, return as empty stream */
     586           4 :                                                 *ptr = (char *)php_stream_memory_open(TEMP_STREAM_READONLY, "", 0);
     587           4 :                                                 PQfreemem(tmp_ptr);
     588           4 :                                                 *len = 0;
     589             :                                         } else {
     590           2 :                                                 *ptr = estrndup(tmp_ptr, tmp_len);
     591           2 :                                                 PQfreemem(tmp_ptr);
     592           2 :                                                 *len = tmp_len;
     593           2 :                                                 *caller_frees = 1;
     594             :                                         }
     595             :                                 }
     596           6 :                                 break;
     597         354 :                         case PDO_PARAM_NULL:
     598             :                         case PDO_PARAM_STR:
     599             :                         case PDO_PARAM_STMT:
     600             :                         case PDO_PARAM_INPUT_OUTPUT:
     601             :                         case PDO_PARAM_ZVAL:
     602             :                         default:
     603         354 :                                 break;
     604             :                 }
     605             :         }
     606             : 
     607         633 :         return 1;
     608             : }
     609             : 
     610             : static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, PGconn *conn)
     611             : {
     612           9 :         char *table_name = NULL;
     613             :         PGresult *tmp_res;
     614           9 :         char *querystr = NULL;
     615             : 
     616           9 :         spprintf(&querystr, 0, "SELECT RELNAME FROM PG_CLASS WHERE OID=%d", oid);
     617             : 
     618           9 :         if ((tmp_res = PQexec(conn, querystr)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
     619           0 :                 if (tmp_res) {
     620           0 :                         PQclear(tmp_res);
     621             :                 }
     622           0 :                 efree(querystr);
     623           0 :                 return 0;
     624             :         }
     625           9 :         efree(querystr);
     626             : 
     627           9 :         if (1 == PQgetisnull(tmp_res, 0, 0) || (table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
     628           0 :                 PQclear(tmp_res);
     629           0 :                 return 0;
     630             :         }
     631             : 
     632           9 :         table_name = estrdup(table_name);
     633             : 
     634           9 :         PQclear(tmp_res);
     635           9 :         return table_name;
     636             : }
     637             : 
     638           9 : static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
     639             : {
     640           9 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     641             :         PGresult *res;
     642           9 :         char *q=NULL;
     643             :         ExecStatusType status;
     644             :         Oid table_oid;
     645           9 :         char *table_name=NULL;
     646             : 
     647           9 :         if (!S->result) {
     648           0 :                 return FAILURE;
     649             :         }
     650             : 
     651           9 :         if (colno >= stmt->column_count) {
     652           0 :                 return FAILURE;
     653             :         }
     654             : 
     655           9 :         array_init(return_value);
     656           9 :         add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type);
     657             : 
     658           9 :         table_oid = PQftable(S->result, colno);
     659           9 :         add_assoc_long(return_value, "pgsql:table_oid", table_oid);
     660          18 :         table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H->server);
     661           9 :         if (table_name) {
     662           9 :                 add_assoc_string(return_value, "table", table_name);
     663           9 :                 efree(table_name);
     664             :         }
     665             : 
     666           9 :         switch (S->cols[colno].pgsql_type) {
     667           1 :                 case BOOLOID:
     668           1 :                         add_assoc_string(return_value, "native_type", BOOLLABEL);
     669           1 :                         break;
     670           1 :                 case BYTEAOID:
     671           1 :                         add_assoc_string(return_value, "native_type", BYTEALABEL);
     672           1 :                         break;
     673           1 :                 case INT8OID:
     674           1 :                         add_assoc_string(return_value, "native_type", INT8LABEL);
     675           1 :                         break;
     676           1 :                 case INT2OID:
     677           1 :                         add_assoc_string(return_value, "native_type", INT2LABEL);
     678           1 :                         break;
     679           1 :                 case INT4OID:
     680           1 :                         add_assoc_string(return_value, "native_type", INT4LABEL);
     681           1 :                         break;
     682           1 :                 case TEXTOID:
     683           1 :                         add_assoc_string(return_value, "native_type", TEXTLABEL);
     684           1 :                         break;
     685           1 :                 case VARCHAROID:
     686           1 :                         add_assoc_string(return_value, "native_type", VARCHARLABEL);
     687           1 :                         break;
     688           1 :                 case DATEOID:
     689           1 :                         add_assoc_string(return_value, "native_type", DATELABEL);
     690           1 :                         break;
     691           1 :                 case TIMESTAMPOID:
     692           1 :                         add_assoc_string(return_value, "native_type", TIMESTAMPLABEL);
     693           1 :                         break;
     694           0 :                 default:
     695             :                         /* Fetch metadata from Postgres system catalogue */
     696           0 :                         spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%u", S->cols[colno].pgsql_type);
     697           0 :                         res = PQexec(S->H->server, q);
     698           0 :                         efree(q);
     699           0 :                         status = PQresultStatus(res);
     700           0 :                         if (status == PGRES_TUPLES_OK && 1 == PQntuples(res)) {
     701           0 :                                 add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0));
     702             :                         }
     703           0 :                         PQclear(res);
     704             :         }
     705           9 :         return 1;
     706             : }
     707             : 
     708        1028 : static int pdo_pgsql_stmt_cursor_closer(pdo_stmt_t *stmt)
     709             : {
     710        1028 :         pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
     711             : 
     712        1028 :         if (S->cols != NULL){
     713        1028 :                 efree(S->cols);
     714        1028 :                 S->cols = NULL;
     715             :         }
     716        1028 :         return 1;
     717             : }
     718             : 
     719             : struct pdo_stmt_methods pgsql_stmt_methods = {
     720             :         pgsql_stmt_dtor,
     721             :         pgsql_stmt_execute,
     722             :         pgsql_stmt_fetch,
     723             :         pgsql_stmt_describe,
     724             :         pgsql_stmt_get_col,
     725             :         pgsql_stmt_param_hook,
     726             :         NULL, /* set_attr */
     727             :         NULL, /* get_attr */
     728             :         pgsql_stmt_get_column_meta,
     729             :         NULL,  /* next_rowset */
     730             :         pdo_pgsql_stmt_cursor_closer
     731             : };
     732             : 
     733             : /*
     734             :  * Local variables:
     735             :  * tab-width: 4
     736             :  * c-basic-offset: 4
     737             :  * End:
     738             :  * vim600: noet sw=4 ts=4 fdm=marker
     739             :  * vim<600: noet sw=4 ts=4
     740             :  */

Generated by: LCOV version 1.10

Generated at Sun, 16 Jan 2022 08:19:18 +0000 (6 days ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.