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/interbase - ibase_query.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 666 897 74.2 %
Date: 2017-09-08 Functions: 28 30 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2017 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: Ard Biesheuvel <a.k.biesheuvel@its.tudelft.nl>              |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #include "config.h"
      21             : #endif
      22             : 
      23             : #include "php.h"
      24             : #include "php_ini.h"
      25             : 
      26             : #if HAVE_IBASE
      27             : 
      28             : #include "ext/standard/php_standard.h"
      29             : #include "php_interbase.h"
      30             : #include "php_ibase_includes.h"
      31             : 
      32             : #define ISC_LONG_MIN    INT_MIN
      33             : #define ISC_LONG_MAX    INT_MAX
      34             : 
      35             : #define QUERY_RESULT    1
      36             : #define EXECUTE_RESULT  2
      37             : 
      38             : #define FETCH_ROW               1
      39             : #define FETCH_ARRAY             2
      40             : 
      41             : typedef struct {
      42             :         ISC_ARRAY_DESC ar_desc;
      43             :         ISC_LONG ar_size; /* size of entire array in bytes */
      44             :         unsigned short el_type, el_size;
      45             : } ibase_array;
      46             : 
      47             : typedef struct {
      48             :         ibase_db_link *link;
      49             :         ibase_trans *trans;
      50             :         struct _ib_query *query;
      51             :         isc_stmt_handle stmt;
      52             :         unsigned short type;
      53             :         unsigned char has_more_rows, statement_type;
      54             :         XSQLDA *out_sqlda;
      55             :         ibase_array out_array[1]; /* last member */
      56             : } ibase_result;
      57             : 
      58             : typedef struct _ib_query {
      59             :         ibase_db_link *link;
      60             :         ibase_trans *trans;
      61             :         ibase_result *result;
      62             :         zend_resource *result_res;
      63             :         isc_stmt_handle stmt;
      64             :         XSQLDA *in_sqlda, *out_sqlda;
      65             :         ibase_array *in_array, *out_array;
      66             :         unsigned short in_array_cnt, out_array_cnt;
      67             :         unsigned short dialect;
      68             :         char statement_type;
      69             :         char *query;
      70             :         zend_resource *trans_res;
      71             : } ibase_query;
      72             : 
      73             : typedef struct {
      74             :         unsigned short vary_length;
      75             :         char vary_string[1];
      76             : } IBVARY;
      77             : 
      78             : /* sql variables union
      79             :  * used for convert and binding input variables
      80             :  */
      81             : typedef struct {
      82             :         union {
      83             :                 short sval;
      84             :                 float fval;
      85             :                 ISC_LONG lval;
      86             :                 ISC_QUAD qval;
      87             :                 ISC_TIMESTAMP tsval;
      88             :                 ISC_DATE dtval;
      89             :                 ISC_TIME tmval;
      90             :         } val;
      91             :         short sqlind;
      92             : } BIND_BUF;
      93             : 
      94             : static int le_result, le_query;
      95             : 
      96             : #define LE_RESULT "Firebird/InterBase result"
      97             : #define LE_QUERY "Firebird/InterBase query"
      98             : 
      99          99 : static void _php_ibase_free_xsqlda(XSQLDA *sqlda) /* {{{ */
     100             : {
     101             :         int i;
     102             :         XSQLVAR *var;
     103             : 
     104             :         IBDEBUG("Free XSQLDA?");
     105          99 :         if (sqlda) {
     106             :                 IBDEBUG("Freeing XSQLDA...");
     107          99 :                 var = sqlda->sqlvar;
     108         449 :                 for (i = 0; i < sqlda->sqld; i++, var++) {
     109         350 :                         efree(var->sqldata);
     110         350 :                         if (var->sqlind) {
     111         316 :                                 efree(var->sqlind);
     112             :                         }
     113             :                 }
     114          99 :                 efree(sqlda);
     115             :         }
     116          99 : }
     117             : /* }}} */
     118             : 
     119         269 : static void _php_ibase_free_stmt_handle(ibase_db_link *link, isc_stmt_handle stmt) /* {{{ */
     120             : {
     121             :         static char info[] = { isc_info_base_level, isc_info_end };
     122             : 
     123         269 :         if (stmt) {
     124             :                 char res_buf[8];
     125             :                 IBDEBUG("Dropping statement handle (free_stmt_handle)...");
     126             :                 /* Only free statement if db-connection is still open */
     127         268 :                 if (SUCCESS == isc_database_info(IB_STATUS, &link->handle,
     128             :                                                         sizeof(info), info, sizeof(res_buf), res_buf)) {
     129         249 :                         if (isc_dsql_free_statement(IB_STATUS, &stmt, DSQL_drop)) {
     130           0 :                                 _php_ibase_error();
     131             :                         }
     132             :                 }
     133             :         }
     134         269 : }
     135             : /* }}} */
     136             : 
     137          99 : static void _php_ibase_free_result(zend_resource *rsrc) /* {{{ */
     138             : {
     139          99 :         ibase_result *ib_result = (ibase_result *) rsrc->ptr;
     140             : 
     141             :         IBDEBUG("Freeing result by dtor...");
     142          99 :         if (ib_result) {
     143          99 :                 _php_ibase_free_xsqlda(ib_result->out_sqlda);
     144          99 :                 if (ib_result->query != NULL) {
     145             :                         IBDEBUG("query still valid; don't drop statement handle");
     146          14 :                         ib_result->query->result = NULL;  /* Indicate to query, that result is released */
     147             :                 } else {
     148          85 :                         _php_ibase_free_stmt_handle(ib_result->link, ib_result->stmt);
     149             :                 }
     150          99 :                 efree(ib_result);
     151             :         }
     152          99 : }
     153             : /* }}} */
     154             : 
     155         269 : static void _php_ibase_free_query(ibase_query *ib_query) /* {{{ */
     156             : {
     157             :         IBDEBUG("Freeing query...");
     158             : 
     159         269 :         if (ib_query->in_sqlda) {
     160          67 :                 efree(ib_query->in_sqlda);
     161             :         }
     162         269 :         if (ib_query->out_sqlda) {
     163          93 :                 efree(ib_query->out_sqlda);
     164             :         }
     165         269 :         if (ib_query->result != NULL) {
     166             :                 IBDEBUG("result still valid; don't drop statement handle");
     167          85 :                 ib_query->result->query = NULL;   /* Indicate to result, that query is released */
     168             :         } else {
     169         184 :                 _php_ibase_free_stmt_handle(ib_query->link, ib_query->stmt);
     170             :         }
     171         269 :         if (ib_query->in_array) {
     172           3 :                 efree(ib_query->in_array);
     173             :         }
     174         269 :         if (ib_query->out_array) {
     175           3 :                 efree(ib_query->out_array);
     176             :         }
     177         269 :         if (ib_query->query) {
     178         269 :                 efree(ib_query->query);
     179             :         }
     180         269 : }
     181             : /* }}} */
     182             : 
     183          11 : static void php_ibase_free_query_rsrc(zend_resource *rsrc) /* {{{ */
     184             : {
     185          11 :         ibase_query *ib_query = (ibase_query *)rsrc->ptr;
     186             : 
     187          11 :         if (ib_query != NULL) {
     188             :                 IBDEBUG("Preparing to free query by dtor...");
     189          11 :                 _php_ibase_free_query(ib_query);
     190          11 :                 efree(ib_query);
     191             :         }
     192          11 : }
     193             : /* }}} */
     194             : 
     195       24608 : void php_ibase_query_minit(INIT_FUNC_ARGS) /* {{{ */
     196             : {
     197       24608 :         le_result = zend_register_list_destructors_ex(_php_ibase_free_result, NULL,
     198             :             "interbase result", module_number);
     199       24608 :         le_query = zend_register_list_destructors_ex(php_ibase_free_query_rsrc, NULL,
     200             :             "interbase query", module_number);
     201       24608 : }
     202             : /* }}} */
     203             : 
     204         160 : static int _php_ibase_alloc_array(ibase_array **ib_arrayp, XSQLDA *sqlda, /* {{{ */
     205             :         isc_db_handle link, isc_tr_handle trans, unsigned short *array_cnt)
     206             : {
     207             :         unsigned short i, n;
     208             :         ibase_array *ar;
     209             : 
     210             :         /* first check if we have any arrays at all */
     211         618 :         for (i = *array_cnt = 0; i < sqlda->sqld; ++i) {
     212         458 :                 if ((sqlda->sqlvar[i].sqltype & ~1) == SQL_ARRAY) {
     213          60 :                         ++*array_cnt;
     214             :                 }
     215             :         }
     216         160 :         if (! *array_cnt) return SUCCESS;
     217             : 
     218           6 :         ar = safe_emalloc(sizeof(ibase_array), *array_cnt, 0);
     219             : 
     220          72 :         for (i = n = 0; i < sqlda->sqld; ++i) {
     221             :                 unsigned short dim;
     222          66 :                 zend_ulong ar_size = 1;
     223          66 :                 XSQLVAR *var = &sqlda->sqlvar[i];
     224             : 
     225          66 :                 if ((var->sqltype & ~1) == SQL_ARRAY) {
     226          60 :                         ibase_array *a = &ar[n++];
     227          60 :                         ISC_ARRAY_DESC *ar_desc = &a->ar_desc;
     228             : 
     229          60 :                         if (isc_array_lookup_bounds(IB_STATUS, &link, &trans, var->relname,
     230             :                                         var->sqlname, ar_desc)) {
     231           0 :                                 _php_ibase_error();
     232           0 :                                 efree(ar);
     233           0 :                                 return FAILURE;
     234             :                         }
     235             : 
     236          60 :                         switch (ar_desc->array_desc_dtype) {
     237             :                                 case blr_text:
     238             :                                 case blr_text2:
     239           6 :                                         a->el_type = SQL_TEXT;
     240           6 :                                         a->el_size = ar_desc->array_desc_length;
     241           6 :                                         break;
     242             :                                 case blr_short:
     243           6 :                                         a->el_type = SQL_SHORT;
     244           6 :                                         a->el_size = sizeof(short);
     245           6 :                                         break;
     246             :                                 case blr_long:
     247          18 :                                         a->el_type = SQL_LONG;
     248          18 :                                         a->el_size = sizeof(ISC_LONG);
     249          18 :                                         break;
     250             :                                 case blr_float:
     251           6 :                                         a->el_type = SQL_FLOAT;
     252           6 :                                         a->el_size = sizeof(float);
     253           6 :                                         break;
     254             :                                 case blr_double:
     255           6 :                                         a->el_type = SQL_DOUBLE;
     256           6 :                                         a->el_size = sizeof(double);
     257           6 :                                         break;
     258             :                                 case blr_int64:
     259           6 :                                         a->el_type = SQL_INT64;
     260           6 :                                         a->el_size = sizeof(ISC_INT64);
     261           6 :                                         break;
     262             :                                 case blr_timestamp:
     263           6 :                                         a->el_type = SQL_TIMESTAMP;
     264           6 :                                         a->el_size = sizeof(ISC_TIMESTAMP);
     265           6 :                                         break;
     266             :                                 case blr_sql_date:
     267           0 :                                         a->el_type = SQL_TYPE_DATE;
     268           0 :                                         a->el_size = sizeof(ISC_DATE);
     269           0 :                                         break;
     270             :                                 case blr_sql_time:
     271           0 :                                         a->el_type = SQL_TYPE_TIME;
     272           0 :                                         a->el_size = sizeof(ISC_TIME);
     273           0 :                                         break;
     274             :                                 case blr_varying:
     275             :                                 case blr_varying2:
     276             :                                         /**
     277             :                                          * IB has a strange way of handling VARCHAR arrays. It doesn't store
     278             :                                          * the length in the first short, as with VARCHAR fields. It does,
     279             :                                          * however, expect the extra short to be allocated for each element.
     280             :                                          */
     281           6 :                                         a->el_type = SQL_TEXT;
     282           6 :                                         a->el_size = ar_desc->array_desc_length + sizeof(short);
     283           6 :                                         break;
     284             :                                 case blr_quad:
     285             :                                 case blr_blob_id:
     286             :                                 case blr_cstring:
     287             :                                 case blr_cstring2:
     288             :                                         /**
     289             :                                          * These types are mentioned as array types in the manual, but I
     290             :                                          * wouldn't know how to create an array field with any of these
     291             :                                          * types. I assume these types are not applicable to arrays, and
     292             :                                          * were mentioned erroneously.
     293             :                                          */
     294             :                                 default:
     295           0 :                                         _php_ibase_module_error("Unsupported array type %d in relation '%s' column '%s'",
     296           0 :                                                 ar_desc->array_desc_dtype, var->relname, var->sqlname);
     297           0 :                                         efree(ar);
     298           0 :                                         return FAILURE;
     299             :                         } /* switch array_desc_type */
     300             : 
     301             :                         /* calculate elements count */
     302         132 :                         for (dim = 0; dim < ar_desc->array_desc_dimensions; dim++) {
     303          72 :                                 ar_size *= 1 + ar_desc->array_desc_bounds[dim].array_bound_upper
     304          72 :                                         -ar_desc->array_desc_bounds[dim].array_bound_lower;
     305             :                         }
     306          60 :                         a->ar_size = a->el_size * ar_size;
     307             :                 } /* if SQL_ARRAY */
     308             :         } /* for column */
     309           6 :         *ib_arrayp = ar;
     310           6 :         return SUCCESS;
     311             : }
     312             : /* }}} */
     313             : 
     314             : /* allocate and prepare query */
     315         273 : static int _php_ibase_alloc_query(ibase_query *ib_query, ibase_db_link *link, /* {{{ */
     316             :         ibase_trans *trans, char *query, unsigned short dialect, zend_resource *trans_res)
     317             : {
     318             :         static char info_type[] = {isc_info_sql_stmt_type};
     319             :         char result[8];
     320             : 
     321             :         /* Return FAILURE, if querystring is empty */
     322         273 :         if (*query == '\0') {
     323           0 :                 php_error_docref(NULL, E_WARNING, "Querystring empty.");
     324           0 :                 return FAILURE;
     325             :         }
     326             : 
     327         273 :         ib_query->link = link;
     328         273 :         ib_query->trans = trans;
     329         273 :         ib_query->result_res = NULL;
     330         273 :         ib_query->result = NULL;
     331         273 :         ib_query->stmt = 0;
     332         273 :         ib_query->in_array = NULL;
     333         273 :         ib_query->out_array = NULL;
     334         273 :         ib_query->dialect = dialect;
     335         273 :         ib_query->query = estrdup(query);
     336         273 :         ib_query->trans_res = trans_res;
     337         273 :         ib_query->out_sqlda = NULL;
     338         273 :         ib_query->in_sqlda = NULL;
     339             : 
     340         273 :         if (isc_dsql_allocate_statement(IB_STATUS, &link->handle, &ib_query->stmt)) {
     341           0 :                 _php_ibase_error();
     342           0 :                 goto _php_ibase_alloc_query_error;
     343             :         }
     344             : 
     345         273 :         ib_query->out_sqlda = (XSQLDA *) emalloc(XSQLDA_LENGTH(1));
     346         273 :         ib_query->out_sqlda->sqln = 1;
     347         273 :         ib_query->out_sqlda->version = SQLDA_CURRENT_VERSION;
     348             : 
     349         273 :         if (isc_dsql_prepare(IB_STATUS, &ib_query->trans->handle, &ib_query->stmt,
     350             :                         0, query, dialect, ib_query->out_sqlda)) {
     351           4 :                 _php_ibase_error();
     352           4 :                 goto _php_ibase_alloc_query_error;
     353             :         }
     354             : 
     355             :         /* find out what kind of statement was prepared */
     356         269 :         if (isc_dsql_sql_info(IB_STATUS, &ib_query->stmt, sizeof(info_type),
     357             :                         info_type, sizeof(result), result)) {
     358           0 :                 _php_ibase_error();
     359           0 :                 goto _php_ibase_alloc_query_error;
     360             :         }
     361         269 :         ib_query->statement_type = result[3];
     362             : 
     363             :         /* not enough output variables ? */
     364         269 :         if (ib_query->out_sqlda->sqld > ib_query->out_sqlda->sqln) {
     365          28 :                 ib_query->out_sqlda = erealloc(ib_query->out_sqlda, XSQLDA_LENGTH(ib_query->out_sqlda->sqld));
     366          28 :                 ib_query->out_sqlda->sqln = ib_query->out_sqlda->sqld;
     367          28 :                 ib_query->out_sqlda->version = SQLDA_CURRENT_VERSION;
     368          28 :                 if (isc_dsql_describe(IB_STATUS, &ib_query->stmt, SQLDA_CURRENT_VERSION, ib_query->out_sqlda)) {
     369           0 :                         _php_ibase_error();
     370           0 :                         goto _php_ibase_alloc_query_error;
     371             :                 }
     372             :         }
     373             : 
     374             :         /* maybe have input placeholders? */
     375         269 :         ib_query->in_sqlda = emalloc(XSQLDA_LENGTH(1));
     376         269 :         ib_query->in_sqlda->sqln = 1;
     377         269 :         ib_query->in_sqlda->version = SQLDA_CURRENT_VERSION;
     378         269 :         if (isc_dsql_describe_bind(IB_STATUS, &ib_query->stmt, SQLDA_CURRENT_VERSION, ib_query->in_sqlda)) {
     379           0 :                 _php_ibase_error();
     380           0 :                 goto _php_ibase_alloc_query_error;
     381             :         }
     382             : 
     383             :         /* not enough input variables ? */
     384         269 :         if (ib_query->in_sqlda->sqln < ib_query->in_sqlda->sqld) {
     385          12 :                 ib_query->in_sqlda = erealloc(ib_query->in_sqlda, XSQLDA_LENGTH(ib_query->in_sqlda->sqld));
     386          12 :                 ib_query->in_sqlda->sqln = ib_query->in_sqlda->sqld;
     387          12 :                 ib_query->in_sqlda->version = SQLDA_CURRENT_VERSION;
     388             : 
     389          12 :                 if (isc_dsql_describe_bind(IB_STATUS, &ib_query->stmt,
     390             :                                 SQLDA_CURRENT_VERSION, ib_query->in_sqlda)) {
     391           0 :                         _php_ibase_error();
     392           0 :                         goto _php_ibase_alloc_query_error;
     393             :                 }
     394             :         }
     395             : 
     396             :         /* no, haven't placeholders at all */
     397         269 :         if (ib_query->in_sqlda->sqld == 0) {
     398         202 :                 efree(ib_query->in_sqlda);
     399         202 :                 ib_query->in_sqlda = NULL;
     400          67 :         } else if (FAILURE == _php_ibase_alloc_array(&ib_query->in_array, ib_query->in_sqlda,
     401             :                         link->handle, trans->handle, &ib_query->in_array_cnt)) {
     402           0 :                 goto _php_ibase_alloc_query_error;
     403             :         }
     404             : 
     405         269 :         if (ib_query->out_sqlda->sqld == 0) {
     406         176 :                 efree(ib_query->out_sqlda);
     407         176 :                 ib_query->out_sqlda = NULL;
     408          93 :         } else  if (FAILURE == _php_ibase_alloc_array(&ib_query->out_array, ib_query->out_sqlda,
     409             :                         link->handle, trans->handle, &ib_query->out_array_cnt)) {
     410           0 :                 goto _php_ibase_alloc_query_error;
     411             :         }
     412             : 
     413         269 :         return SUCCESS;
     414             : 
     415             : _php_ibase_alloc_query_error:
     416             : 
     417           4 :         if (ib_query->out_sqlda) {
     418           4 :                 efree(ib_query->out_sqlda);
     419             :         }
     420           4 :         if (ib_query->in_sqlda) {
     421           0 :                 efree(ib_query->in_sqlda);
     422             :         }
     423           4 :         if (ib_query->out_array) {
     424           0 :                 efree(ib_query->out_array);
     425             :         }
     426           4 :         if (ib_query->query) {
     427           4 :                 efree(ib_query->query);
     428             :         }
     429           4 :         return FAILURE;
     430             : }
     431             : /* }}} */
     432             : 
     433        3630 : static int _php_ibase_bind_array(zval *val, char *buf, zend_ulong buf_size, /* {{{ */
     434             :         ibase_array *array, int dim)
     435             : {
     436        3630 :         zval null_val, *pnull_val = &null_val;
     437        3630 :         int u_bound = array->ar_desc.array_desc_bounds[dim].array_bound_upper,
     438        3630 :                 l_bound = array->ar_desc.array_desc_bounds[dim].array_bound_lower,
     439        3630 :                 dim_len = 1 + u_bound - l_bound;
     440             : 
     441        3630 :         ZVAL_NULL(pnull_val);
     442             : 
     443        3630 :         if (dim < array->ar_desc.array_desc_dimensions) {
     444         360 :                 zend_ulong slice_size = buf_size / dim_len;
     445             :                 unsigned short i;
     446         360 :                 zval *subval = val;
     447             : 
     448         360 :                 if (Z_TYPE_P(val) == IS_ARRAY) {
     449         360 :                         zend_hash_internal_pointer_reset(Z_ARRVAL_P(val));
     450             :                 }
     451             : 
     452        3960 :                 for (i = 0; i < dim_len; ++i) {
     453             : 
     454        7200 :                         if (Z_TYPE_P(val) == IS_ARRAY &&
     455        3600 :                                 (subval = zend_hash_get_current_data(Z_ARRVAL_P(val))) == NULL)
     456             :                         {
     457           0 :                                 subval = pnull_val;
     458             :                         }
     459             : 
     460        3600 :                         if (_php_ibase_bind_array(subval, buf, slice_size, array, dim+1) == FAILURE)
     461             :                         {
     462           0 :                                 return FAILURE;
     463             :                         }
     464        3600 :                         buf += slice_size;
     465             : 
     466        3600 :                         if (Z_TYPE_P(val) == IS_ARRAY) {
     467        3600 :                                 zend_hash_move_forward(Z_ARRVAL_P(val));
     468             :                         }
     469             :                 }
     470             : 
     471         360 :                 if (Z_TYPE_P(val) == IS_ARRAY) {
     472         360 :                         zend_hash_internal_pointer_reset(Z_ARRVAL_P(val));
     473             :                 }
     474             : 
     475             :         } else {
     476             :                 /* expect a single value */
     477        3270 :                 if (Z_TYPE_P(val) == IS_NULL) {
     478           0 :                         memset(buf, 0, buf_size);
     479        3270 :                 } else if (array->ar_desc.array_desc_scale < 0) {
     480             : 
     481             :                         /* no coercion for array types */
     482             :                         double l;
     483             : 
     484          60 :                         convert_to_double(val);
     485             : 
     486          60 :                         if (Z_DVAL_P(val) > 0) {
     487          39 :                                 l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale) + .5;
     488             :                         } else {
     489          21 :                                 l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale) - .5;
     490             :                         }
     491             : 
     492          60 :                         switch (array->el_type) {
     493             :                                 case SQL_SHORT:
     494           0 :                                         if (l > SHRT_MAX || l < SHRT_MIN) {
     495           0 :                                                 _php_ibase_module_error("Array parameter exceeds field width");
     496           0 :                                                 return FAILURE;
     497             :                                         }
     498           0 :                                         *(short*) buf = (short) l;
     499           0 :                                         break;
     500             :                                 case SQL_LONG:
     501          30 :                                         if (l > ISC_LONG_MAX || l < ISC_LONG_MIN) {
     502           0 :                                                 _php_ibase_module_error("Array parameter exceeds field width");
     503           0 :                                                 return FAILURE;
     504             :                                         }
     505          30 :                                         *(ISC_LONG*) buf = (ISC_LONG) l;
     506          30 :                                         break;
     507             :                                 case SQL_INT64:
     508             :                                         {
     509             :                                                 long double l;
     510             : 
     511          30 :                                                 convert_to_string(val);
     512             : 
     513          30 :                                                 if (!sscanf(Z_STRVAL_P(val), "%Lf", &l)) {
     514           0 :                                                         _php_ibase_module_error("Cannot convert '%s' to long double",
     515           0 :                                                                  Z_STRVAL_P(val));
     516           0 :                                                         return FAILURE;
     517             :                                                 }
     518             : 
     519          30 :                                                 if (l > 0) {
     520          42 :                                                         *(ISC_INT64 *) buf = (ISC_INT64) (l * pow(10,
     521          21 :                                                                 -array->ar_desc.array_desc_scale) + .5);
     522             :                                                 } else {
     523          18 :                                                         *(ISC_INT64 *) buf = (ISC_INT64) (l * pow(10,
     524           9 :                                                                 -array->ar_desc.array_desc_scale) - .5);
     525             :                                                 }
     526             :                                         }
     527             :                                         break;
     528             :                         }
     529             :                 } else {
     530        3210 :                         struct tm t = { 0, 0, 0, 0, 0, 0 };
     531             : 
     532        3210 :                         switch (array->el_type) {
     533             : #ifndef HAVE_STRPTIME
     534             :                                 unsigned short n;
     535             : #endif
     536             : #if (SIZEOF_ZEND_LONG < 8)
     537             :                                 ISC_INT64 l;
     538             : #endif
     539             : 
     540             :                                 case SQL_SHORT:
     541          30 :                                         convert_to_long(val);
     542          30 :                                         if (Z_LVAL_P(val) > SHRT_MAX || Z_LVAL_P(val) < SHRT_MIN) {
     543           0 :                                                 _php_ibase_module_error("Array parameter exceeds field width");
     544           0 :                                                 return FAILURE;
     545             :                                         }
     546          30 :                                         *(short *) buf = (short) Z_LVAL_P(val);
     547          30 :                                         break;
     548             :                                 case SQL_LONG:
     549        3030 :                                         convert_to_long(val);
     550             : #if (SIZEOF_ZEND_LONG > 4)
     551        3030 :                                         if (Z_LVAL_P(val) > ISC_LONG_MAX || Z_LVAL_P(val) < ISC_LONG_MIN) {
     552           0 :                                                 _php_ibase_module_error("Array parameter exceeds field width");
     553           0 :                                                 return FAILURE;
     554             :                                         }
     555             : #endif
     556        3030 :                                         *(ISC_LONG *) buf = (ISC_LONG) Z_LVAL_P(val);
     557        3030 :                                         break;
     558             :                                 case SQL_INT64:
     559             : #if (SIZEOF_ZEND_LONG >= 8)
     560           0 :                                         convert_to_long(val);
     561           0 :                                         *(zend_long *) buf = Z_LVAL_P(val);
     562             : #else
     563             :                                         convert_to_string(val);
     564             :                                         if (!sscanf(Z_STRVAL_P(val), "%" LL_MASK "d", &l)) {
     565             :                                                 _php_ibase_module_error("Cannot convert '%s' to long integer",
     566             :                                                          Z_STRVAL_P(val));
     567             :                                                 return FAILURE;
     568             :                                         } else {
     569             :                                                 *(ISC_INT64 *) buf = l;
     570             :                                         }
     571             : #endif
     572           0 :                                         break;
     573             :                                 case SQL_FLOAT:
     574          30 :                                         convert_to_double(val);
     575          30 :                                         *(float*) buf = (float) Z_DVAL_P(val);
     576          30 :                                         break;
     577             :                                 case SQL_DOUBLE:
     578          30 :                                         convert_to_double(val);
     579          30 :                                         *(double*) buf = Z_DVAL_P(val);
     580          30 :                                         break;
     581             :                                 case SQL_TIMESTAMP:
     582          30 :                                         convert_to_string(val);
     583             : #ifdef HAVE_STRPTIME
     584          30 :                                         strptime(Z_STRVAL_P(val), INI_STR("ibase.timestampformat"), &t);
     585             : #else
     586             :                                         n = sscanf(Z_STRVAL_P(val), "%d%*[/]%d%*[/]%d %d%*[:]%d%*[:]%d",
     587             :                                                 &t.tm_mon, &t.tm_mday, &t.tm_year, &t.tm_hour, &t.tm_min, &t.tm_sec);
     588             : 
     589             :                                         if (n != 3 && n != 6) {
     590             :                                                 _php_ibase_module_error("Invalid date/time format (expected 3 or 6 fields, got %d."
     591             :                                                         " Use format 'm/d/Y H:i:s'. You gave '%s')", n, Z_STRVAL_P(val));
     592             :                                                 return FAILURE;
     593             :                                         }
     594             :                                         t.tm_year -= 1900;
     595             :                                         t.tm_mon--;
     596             : #endif
     597          30 :                                         isc_encode_timestamp(&t, (ISC_TIMESTAMP * ) buf);
     598          30 :                                         break;
     599             :                                 case SQL_TYPE_DATE:
     600           0 :                                         convert_to_string(val);
     601             : #ifdef HAVE_STRPTIME
     602           0 :                                         strptime(Z_STRVAL_P(val), INI_STR("ibase.dateformat"), &t);
     603             : #else
     604             :                                         n = sscanf(Z_STRVAL_P(val), "%d%*[/]%d%*[/]%d", &t.tm_mon, &t.tm_mday, &t.tm_year);
     605             : 
     606             :                                         if (n != 3) {
     607             :                                                 _php_ibase_module_error("Invalid date format (expected 3 fields, got %d. "
     608             :                                                         "Use format 'm/d/Y' You gave '%s')", n, Z_STRVAL_P(val));
     609             :                                                 return FAILURE;
     610             :                                         }
     611             :                                         t.tm_year -= 1900;
     612             :                                         t.tm_mon--;
     613             : #endif
     614           0 :                                         isc_encode_sql_date(&t, (ISC_DATE *) buf);
     615           0 :                                         break;
     616             :                                 case SQL_TYPE_TIME:
     617           0 :                                         convert_to_string(val);
     618             : #ifdef HAVE_STRPTIME
     619           0 :                                         strptime(Z_STRVAL_P(val), INI_STR("ibase.timeformat"), &t);
     620             : #else
     621             :                                         n = sscanf(Z_STRVAL_P(val), "%d%*[:]%d%*[:]%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
     622             : 
     623             :                                         if (n != 3) {
     624             :                                                 _php_ibase_module_error("Invalid time format (expected 3 fields, got %d. "
     625             :                                                         "Use format 'H:i:s'. You gave '%s')", n, Z_STRVAL_P(val));
     626             :                                                 return FAILURE;
     627             :                                         }
     628             : #endif
     629           0 :                                         isc_encode_sql_time(&t, (ISC_TIME *) buf);
     630           0 :                                         break;
     631             :                                 default:
     632          60 :                                         convert_to_string(val);
     633          60 :                                         strlcpy(buf, Z_STRVAL_P(val), buf_size);
     634             :                         }
     635             :                 }
     636             :         }
     637        3630 :         return SUCCESS;
     638             : }
     639             : /* }}} */
     640             : 
     641          82 : static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */
     642             :         ibase_query *ib_query)
     643             : {
     644          82 :         int i, array_cnt = 0, rv = SUCCESS;
     645             : 
     646         227 :         for (i = 0; i < sqlda->sqld; ++i) { /* bound vars */
     647             : 
     648         145 :                 zval *b_var = &b_vars[i];
     649         145 :                 XSQLVAR *var = &sqlda->sqlvar[i];
     650             : 
     651         145 :                 var->sqlind = &buf[i].sqlind;
     652             : 
     653             :                 /* check if a NULL should be inserted */
     654         145 :                 switch (Z_TYPE_P(b_var)) {
     655             :                         int force_null;
     656             : 
     657             :                         case IS_STRING:
     658             : 
     659          61 :                                 force_null = 0;
     660             : 
     661             :                                 /* for these types, an empty string can be handled like a NULL value */
     662          61 :                                 switch (var->sqltype & ~1) {
     663             :                                         case SQL_SHORT:
     664             :                                         case SQL_LONG:
     665             :                                         case SQL_INT64:
     666             :                                         case SQL_FLOAT:
     667             :                                         case SQL_DOUBLE:
     668             :                                         case SQL_TIMESTAMP:
     669             :                                         case SQL_TYPE_DATE:
     670             :                                         case SQL_TYPE_TIME:
     671          40 :                                                 force_null = (Z_STRLEN_P(b_var) == 0);
     672             :                                 }
     673             : 
     674          61 :                                 if (! force_null) break;
     675             : 
     676             :                         case IS_NULL:
     677           1 :                                         buf[i].sqlind = -1;
     678             : 
     679           1 :                                 if (var->sqltype & SQL_ARRAY) ++array_cnt;
     680             : 
     681           1 :                                 continue;
     682             :                 }
     683             : 
     684             :                 /* if we make it to this point, we must provide a value for the parameter */
     685             : 
     686         144 :                 buf[i].sqlind = 0;
     687             : 
     688         144 :                 var->sqldata = (void*)&buf[i].val;
     689             : 
     690         144 :                 switch (var->sqltype & ~1) {
     691             :                         struct tm t;
     692             : 
     693             :                         case SQL_TIMESTAMP:
     694             :                         case SQL_TYPE_DATE:
     695             :                         case SQL_TYPE_TIME:
     696          12 :                                 if (Z_TYPE_P(b_var) == IS_LONG) {
     697             :                                         struct tm *res;
     698           6 :                                         res = php_gmtime_r(&Z_LVAL_P(b_var), &t);
     699           6 :                                         if (!res) {
     700           0 :                                                 return FAILURE;
     701             :                                         }
     702             :                                 } else {
     703             : #ifdef HAVE_STRPTIME
     704           6 :                                         char *format = INI_STR("ibase.timestampformat");
     705             : 
     706           6 :                                         convert_to_string(b_var);
     707             : 
     708           6 :                                         switch (var->sqltype & ~1) {
     709             :                                                 case SQL_TYPE_DATE:
     710           0 :                                                         format = INI_STR("ibase.dateformat");
     711           0 :                                                         break;
     712             :                                                 case SQL_TYPE_TIME:
     713           0 :                                                         format = INI_STR("ibase.timeformat");
     714             :                                         }
     715           6 :                                         if (!strptime(Z_STRVAL_P(b_var), format, &t)) {
     716             :                                                 /* strptime() cannot handle it, so let IB have a try */
     717           0 :                                                 break;
     718             :                                         }
     719             : #else /* ifndef HAVE_STRPTIME */
     720             :                                         break; /* let IB parse it as a string */
     721             : #endif
     722             :                                 }
     723             : 
     724          12 :                                 switch (var->sqltype & ~1) {
     725             :                                         default: /* == case SQL_TIMESTAMP */
     726          12 :                                                 isc_encode_timestamp(&t, &buf[i].val.tsval);
     727          12 :                                                 break;
     728             :                                         case SQL_TYPE_DATE:
     729           0 :                                                 isc_encode_sql_date(&t, &buf[i].val.dtval);
     730           0 :                                                 break;
     731             :                                         case SQL_TYPE_TIME:
     732           0 :                                                 isc_encode_sql_time(&t, &buf[i].val.tmval);
     733             :                                                 break;
     734             :                                 }
     735          12 :                                 continue;
     736             : 
     737             :                         case SQL_BLOB:
     738             : 
     739           4 :                                 convert_to_string(b_var);
     740             : 
     741           7 :                                 if (Z_STRLEN_P(b_var) != BLOB_ID_LEN ||
     742           3 :                                         !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) {
     743             : 
     744           1 :                                         ibase_blob ib_blob = { 0, BLOB_INPUT };
     745             : 
     746           1 :                                         if (isc_create_blob(IB_STATUS, &ib_query->link->handle,
     747           1 :                                                         &ib_query->trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) {
     748           0 :                                                 _php_ibase_error();
     749           0 :                                                 return FAILURE;
     750             :                                         }
     751             : 
     752           1 :                                         if (_php_ibase_blob_add(b_var, &ib_blob) != SUCCESS) {
     753           0 :                                                 return FAILURE;
     754             :                                         }
     755             : 
     756           1 :                                         if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
     757           0 :                                                 _php_ibase_error();
     758           0 :                                                 return FAILURE;
     759             :                                         }
     760           1 :                                         buf[i].val.qval = ib_blob.bl_qd;
     761             :                                 }
     762           4 :                                 continue;
     763             : 
     764             :                         case SQL_ARRAY:
     765             : 
     766          30 :                                 if (Z_TYPE_P(b_var) != IS_ARRAY) {
     767           0 :                                         convert_to_string(b_var);
     768             : 
     769           0 :                                         if (Z_STRLEN_P(b_var) != BLOB_ID_LEN ||
     770           0 :                                                 !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) {
     771             : 
     772           0 :                                                 _php_ibase_module_error("Parameter %d: invalid array ID",i+1);
     773           0 :                                                 rv = FAILURE;
     774             :                                         }
     775             :                                 } else {
     776             :                                         /* convert the array data into something IB can understand */
     777          30 :                                         ibase_array *ar = &ib_query->in_array[array_cnt];
     778          30 :                                         void *array_data = emalloc(ar->ar_size);
     779          30 :                                         ISC_QUAD array_id = { 0, 0 };
     780             : 
     781          30 :                                         if (FAILURE == _php_ibase_bind_array(b_var, array_data, ar->ar_size,
     782             :                                                         ar, 0)) {
     783           0 :                                                 _php_ibase_module_error("Parameter %d: failed to bind array argument", i+1);
     784           0 :                                                 efree(array_data);
     785           0 :                                                 rv = FAILURE;
     786           0 :                                                 continue;
     787             :                                         }
     788             : 
     789          60 :                                         if (isc_array_put_slice(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle,
     790          30 :                                                         &array_id, &ar->ar_desc, array_data, &ar->ar_size)) {
     791           0 :                                                 _php_ibase_error();
     792           0 :                                                 efree(array_data);
     793           0 :                                                 return FAILURE;
     794             :                                         }
     795          30 :                                         buf[i].val.qval = array_id;
     796          30 :                                         efree(array_data);
     797             :                                 }
     798          30 :                                 ++array_cnt;
     799          30 :                                 continue;
     800             :                         } /* switch */
     801             : 
     802             :                         /* we end up here if none of the switch cases handled the field */
     803          98 :                         convert_to_string(b_var);
     804          98 :                         var->sqldata = Z_STRVAL_P(b_var);
     805          98 :                         var->sqllen   = Z_STRLEN_P(b_var);
     806          98 :                         var->sqltype = SQL_TEXT;
     807             :         } /* for */
     808          82 :         return rv;
     809             : }
     810             : /* }}} */
     811             : 
     812          99 : static void _php_ibase_alloc_xsqlda(XSQLDA *sqlda) /* {{{ */
     813             : {
     814             :         int i;
     815             : 
     816         449 :         for (i = 0; i < sqlda->sqld; i++) {
     817         350 :                 XSQLVAR *var = &sqlda->sqlvar[i];
     818             : 
     819         350 :                 switch (var->sqltype & ~1) {
     820             :                         case SQL_TEXT:
     821          17 :                                 var->sqldata = safe_emalloc(sizeof(char), var->sqllen, 0);
     822          17 :                                 break;
     823             :                         case SQL_VARYING:
     824          23 :                                 var->sqldata = safe_emalloc(sizeof(char), var->sqllen + sizeof(short), 0);
     825          23 :                                 break;
     826             :                         case SQL_SHORT:
     827          24 :                                 var->sqldata = emalloc(sizeof(short));
     828          24 :                                 break;
     829             :                         case SQL_LONG:
     830         174 :                                 var->sqldata = emalloc(sizeof(ISC_LONG));
     831         174 :                                 break;
     832             :                         case SQL_FLOAT:
     833          17 :                                 var->sqldata = emalloc(sizeof(float));
     834          17 :                                         break;
     835             :                         case SQL_DOUBLE:
     836          17 :                                 var->sqldata = emalloc(sizeof(double));
     837          17 :                                 break;
     838             :                         case SQL_INT64:
     839          27 :                                 var->sqldata = emalloc(sizeof(ISC_INT64));
     840          27 :                                 break;
     841             :                         case SQL_TIMESTAMP:
     842          17 :                                 var->sqldata = emalloc(sizeof(ISC_TIMESTAMP));
     843          17 :                                 break;
     844             :                         case SQL_TYPE_DATE:
     845           0 :                                 var->sqldata = emalloc(sizeof(ISC_DATE));
     846           0 :                                 break;
     847             :                         case SQL_TYPE_TIME:
     848           0 :                                 var->sqldata = emalloc(sizeof(ISC_TIME));
     849           0 :                                 break;
     850             :                         case SQL_BLOB:
     851             :                         case SQL_ARRAY:
     852          34 :                                 var->sqldata = emalloc(sizeof(ISC_QUAD));
     853             :                                 break;
     854             :                 } /* switch */
     855             : 
     856         350 :                 if (var->sqltype & 1) { /* sql NULL flag */
     857         316 :                         var->sqlind = emalloc(sizeof(short));
     858             :                 } else {
     859          34 :                         var->sqlind = NULL;
     860             :                 }
     861             :         } /* for */
     862          99 : }
     863             : /* }}} */
     864             : 
     865         284 : static int _php_ibase_exec(INTERNAL_FUNCTION_PARAMETERS, ibase_result **ib_resultp, /* {{{ */
     866             :         ibase_query *ib_query, zval *args)
     867             : {
     868         284 :         XSQLDA *in_sqlda = NULL, *out_sqlda = NULL;
     869         284 :         BIND_BUF *bind_buf = NULL;
     870         284 :         int i, rv = FAILURE;
     871             :         static char info_count[] = { isc_info_sql_records };
     872             :         char result[64];
     873             :         ISC_STATUS isc_result;
     874         284 :         int argc = ib_query->in_sqlda ? ib_query->in_sqlda->sqld : 0;
     875             : 
     876         284 :         RESET_ERRMSG;
     877             : 
     878         429 :         for (i = 0; i < argc; ++i) {
     879         316 :                 SEPARATE_ZVAL(&args[i]);
     880             :         }
     881             : 
     882         284 :         switch (ib_query->statement_type) {
     883             :                 isc_tr_handle tr;
     884             :                 ibase_tr_list **l;
     885             :                 ibase_trans *trans;
     886             : 
     887             :                 case isc_info_sql_stmt_start_trans:
     888             : 
     889             :                         /* a SET TRANSACTION statement should be executed with a NULL trans handle */
     890           2 :                         tr = 0;
     891             : 
     892           4 :                         if (isc_dsql_execute_immediate(IB_STATUS, &ib_query->link->handle, &tr, 0,
     893           4 :                                         ib_query->query, ib_query->dialect, NULL)) {
     894           0 :                                 _php_ibase_error();
     895           0 :                                 goto _php_ibase_exec_error;
     896             :                         }
     897             : 
     898           2 :                         trans = (ibase_trans *) emalloc(sizeof(ibase_trans));
     899           2 :                         trans->handle = tr;
     900           2 :                         trans->link_cnt = 1;
     901           2 :                         trans->affected_rows = 0;
     902           2 :                         trans->db_link[0] = ib_query->link;
     903             : 
     904           2 :                         if (ib_query->link->tr_list == NULL) {
     905           0 :                                 ib_query->link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
     906           0 :                                 ib_query->link->tr_list->trans = NULL;
     907           0 :                                 ib_query->link->tr_list->next = NULL;
     908             :                         }
     909             : 
     910             :                         /* link the transaction into the connection-transaction list */
     911           2 :                         for (l = &ib_query->link->tr_list; *l != NULL; l = &(*l)->next);
     912           2 :                         *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
     913           2 :                         (*l)->trans = trans;
     914           2 :                         (*l)->next = NULL;
     915             : 
     916           2 :                         RETVAL_RES(zend_register_resource(trans, le_trans));
     917           2 :                         Z_TRY_ADDREF_P(return_value);
     918             : 
     919           2 :                         return SUCCESS;
     920             : 
     921             :                 case isc_info_sql_stmt_commit:
     922             :                 case isc_info_sql_stmt_rollback:
     923             : 
     924           0 :                         if (isc_dsql_execute_immediate(IB_STATUS, &ib_query->link->handle,
     925           0 :                                         &ib_query->trans->handle, 0, ib_query->query, ib_query->dialect, NULL)) {
     926           0 :                                 _php_ibase_error();
     927           0 :                                 goto _php_ibase_exec_error;
     928             :                         }
     929             : 
     930           0 :                         if (ib_query->trans->handle == 0 && ib_query->trans_res != NULL) {
     931             :                                 /* transaction was released by the query and was a registered resource,
     932             :                                    so we have to release it */
     933           0 :                                 zend_list_delete(ib_query->trans_res);
     934           0 :                                 ib_query->trans_res = NULL;
     935             :                         }
     936             : 
     937           0 :                         RETVAL_TRUE;
     938             : 
     939           0 :                         return SUCCESS;
     940             : 
     941             :                 default:
     942         282 :                         RETVAL_FALSE;
     943             :         }
     944             : 
     945             :         /* allocate sqlda and output buffers */
     946         282 :         if (ib_query->out_sqlda) { /* output variables in select, select for update */
     947             :                 ibase_result *res;
     948             : 
     949             :                 IBDEBUG("Query wants XSQLDA for output");
     950          99 :                 res = emalloc(sizeof(ibase_result)+sizeof(ibase_array)*max(0,ib_query->out_array_cnt-1));
     951          99 :                 res->link = ib_query->link;
     952          99 :                 res->trans = ib_query->trans;
     953          99 :                 res->stmt = ib_query->stmt;
     954             :                 /* ib_result and ib_query point at each other to handle release of statement handle properly */
     955          99 :                 res->query = ib_query;
     956          99 :                 ib_query->result = res;
     957          99 :                 res->statement_type = ib_query->statement_type;
     958          99 :                 res->has_more_rows = 1;
     959             : 
     960          99 :                 out_sqlda = res->out_sqlda = emalloc(XSQLDA_LENGTH(ib_query->out_sqlda->sqld));
     961          99 :                 memcpy(out_sqlda, ib_query->out_sqlda, XSQLDA_LENGTH(ib_query->out_sqlda->sqld));
     962          99 :                 _php_ibase_alloc_xsqlda(out_sqlda);
     963             : 
     964          99 :                 if (ib_query->out_array) {
     965           3 :                         memcpy(&res->out_array, ib_query->out_array, sizeof(ibase_array)*ib_query->out_array_cnt);
     966             :                 }
     967          99 :                 *ib_resultp = res;
     968             :         }
     969             : 
     970         282 :         if (ib_query->in_sqlda) { /* has placeholders */
     971             :                 IBDEBUG("Query wants XSQLDA for input");
     972          82 :                 in_sqlda = emalloc(XSQLDA_LENGTH(ib_query->in_sqlda->sqld));
     973          82 :                 memcpy(in_sqlda, ib_query->in_sqlda, XSQLDA_LENGTH(ib_query->in_sqlda->sqld));
     974          82 :                 bind_buf = safe_emalloc(sizeof(BIND_BUF), ib_query->in_sqlda->sqld, 0);
     975          82 :                 if (_php_ibase_bind(in_sqlda, args, bind_buf, ib_query) == FAILURE) {
     976             :                         IBDEBUG("Could not bind input XSQLDA");
     977           0 :                         goto _php_ibase_exec_error;
     978             :                 }
     979             :         }
     980             : 
     981         282 :         if (ib_query->statement_type == isc_info_sql_stmt_exec_procedure) {
     982          18 :                 isc_result = isc_dsql_execute2(IB_STATUS, &ib_query->trans->handle,
     983             :                         &ib_query->stmt, SQLDA_CURRENT_VERSION, in_sqlda, out_sqlda);
     984             :         } else {
     985         264 :                 isc_result = isc_dsql_execute(IB_STATUS, &ib_query->trans->handle,
     986             :                         &ib_query->stmt, SQLDA_CURRENT_VERSION, in_sqlda);
     987             :         }
     988         282 :         if (isc_result) {
     989             :                 IBDEBUG("Could not execute query");
     990           1 :                 _php_ibase_error();
     991           1 :                 goto _php_ibase_exec_error;
     992             :         }
     993         281 :         ib_query->trans->affected_rows = 0;
     994             : 
     995         281 :         switch (ib_query->statement_type) {
     996             : 
     997             :                 unsigned long affected_rows;
     998             : 
     999             :                 case isc_info_sql_stmt_insert:
    1000             :                 case isc_info_sql_stmt_update:
    1001             :                 case isc_info_sql_stmt_delete:
    1002             :                 case isc_info_sql_stmt_exec_procedure:
    1003             : 
    1004         127 :                         if (isc_dsql_sql_info(IB_STATUS, &ib_query->stmt, sizeof(info_count),
    1005             :                                         info_count, sizeof(result), result)) {
    1006           0 :                                 _php_ibase_error();
    1007           0 :                                 goto _php_ibase_exec_error;
    1008             :                         }
    1009             : 
    1010         127 :                         affected_rows = 0;
    1011             : 
    1012         127 :                         if (result[0] == isc_info_sql_records) {
    1013         127 :                                 unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
    1014             : 
    1015         762 :                                 while (result[i] != isc_info_end && i < result_size) {
    1016         508 :                                         short len = (short)isc_vax_integer(&result[i+1],2);
    1017         508 :                                         if (result[i] != isc_info_req_select_count) {
    1018         381 :                                                 affected_rows += isc_vax_integer(&result[i+3],len);
    1019             :                                         }
    1020         508 :                                         i += len+3;
    1021             :                                 }
    1022             :                         }
    1023             : 
    1024         127 :                         ib_query->trans->affected_rows = affected_rows;
    1025             : 
    1026         127 :                         if (!ib_query->out_sqlda) { /* no result set is being returned */
    1027         117 :                                 if (affected_rows) {
    1028         108 :                                         RETVAL_LONG(affected_rows);
    1029             :                                 } else {
    1030           9 :                                         RETVAL_TRUE;
    1031             :                                 }
    1032         117 :                                 break;
    1033             :                         }
    1034             :                 default:
    1035         164 :                         RETVAL_TRUE;
    1036             :         }
    1037             : 
    1038         281 :         rv = SUCCESS;
    1039             : 
    1040             : _php_ibase_exec_error:
    1041             : 
    1042         282 :         if (in_sqlda) {
    1043          82 :                 efree(in_sqlda);
    1044             :         }
    1045         282 :         if (bind_buf)
    1046          82 :                 efree(bind_buf);
    1047             : 
    1048         282 :         if (rv == FAILURE) {
    1049           1 :                 if (*ib_resultp) {
    1050           0 :                         efree(*ib_resultp);
    1051           0 :                         *ib_resultp = NULL;
    1052             :                 }
    1053           1 :                 if (out_sqlda) {
    1054           0 :                         _php_ibase_free_xsqlda(out_sqlda);
    1055             :                 }
    1056             :         }
    1057             : 
    1058         282 :         return rv;
    1059             : }
    1060             : /* }}} */
    1061             : 
    1062             : /* {{{ proto mixed ibase_query([resource link_identifier, [ resource link_identifier, ]] string query [, mixed bind_arg [, mixed bind_arg [, ...]]])
    1063             :    Execute a query */
    1064         320 : PHP_FUNCTION(ibase_query)
    1065             : {
    1066         320 :         zval *zlink, *ztrans, *bind_args = NULL;
    1067             :         char *query;
    1068             :         size_t query_len;
    1069             :         int bind_i, bind_num;
    1070         320 :         zend_resource *trans_res = NULL;
    1071         320 :         ibase_db_link *ib_link = NULL;
    1072         320 :         ibase_trans *trans = NULL;
    1073         320 :         ibase_query ib_query = { NULL, NULL, 0, 0 };
    1074         320 :         ibase_result *result = NULL;
    1075             : 
    1076         320 :         RESET_ERRMSG;
    1077             : 
    1078         320 :         RETVAL_FALSE;
    1079             : 
    1080         320 :         switch (ZEND_NUM_ARGS()) {
    1081             :                 zend_long l;
    1082             : 
    1083             :                 default:
    1084           7 :                     if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3, "rrs",
    1085             :                                         &zlink, &ztrans, &query, &query_len)) {
    1086             : 
    1087           0 :                                 ib_link = (ibase_db_link*)zend_fetch_resource2_ex(zlink, LE_LINK, le_link, le_plink);
    1088           0 :                                 trans = (ibase_trans*)zend_fetch_resource_ex(ztrans, LE_TRANS,  le_trans);
    1089             : 
    1090           0 :                                 trans_res = Z_RES_P(ztrans);
    1091           0 :                                 bind_i = 3;
    1092           0 :                                 break;
    1093             :                     }
    1094             :                 case 2:
    1095         249 :                         if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2, "rs",
    1096             :                                         &zlink, &query, &query_len)) {
    1097         135 :                                 _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, zlink, &ib_link, &trans);
    1098             : 
    1099         135 :                                 if (trans != NULL) {
    1100         127 :                                         trans_res = Z_RES_P(zlink);
    1101             :                                 }
    1102         135 :                                 bind_i = 2;
    1103         135 :                                 break;
    1104             :                         }
    1105             : 
    1106             :                         /* the statement is 'CREATE DATABASE ...' if the link argument is IBASE_CREATE */
    1107         287 :                         if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
    1108         173 :                                          "ls", &l, &query, &query_len) && l == PHP_IBASE_CREATE) {
    1109          59 :                                 isc_db_handle db = 0;
    1110          59 :                                 isc_tr_handle trans = 0;
    1111             : 
    1112          59 :                                 if (((l = INI_INT("ibase.max_links")) != -1) && (IBG(num_links) >= l)) {
    1113           0 :                                         _php_ibase_module_error("CREATE DATABASE is not allowed: maximum link count "
    1114             :                                                 "(" ZEND_LONG_FMT ") reached", l);
    1115             : 
    1116          59 :                                 } else if (isc_dsql_execute_immediate(IB_STATUS, &db, &trans, (short)query_len,
    1117             :                                                 query, SQL_DIALECT_CURRENT, NULL)) {
    1118           0 :                                         _php_ibase_error();
    1119             : 
    1120          59 :                                 } else if (!db) {
    1121           0 :                                         _php_ibase_module_error("Connection to created database could not be "
    1122             :                                                 "established");
    1123             : 
    1124             :                                 } else {
    1125             : 
    1126             :                                         /* register the link as a resource; unfortunately, we cannot register
    1127             :                                            it in the hash table, because we don't know the connection params */
    1128          59 :                                         ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link));
    1129          59 :                                         ib_link->handle = db;
    1130          59 :                                         ib_link->dialect = SQL_DIALECT_CURRENT;
    1131          59 :                                         ib_link->tr_list = NULL;
    1132          59 :                                         ib_link->event_head = NULL;
    1133             : 
    1134          59 :                                         RETVAL_RES(zend_register_resource(ib_link, le_link));
    1135          59 :                                         Z_TRY_ADDREF_P(return_value);
    1136          59 :                                         Z_TRY_ADDREF_P(return_value);
    1137          59 :                                         IBG(default_link) = Z_RES_P(return_value);
    1138             :                                 }
    1139          59 :                                 return;
    1140             :                         }
    1141             :                 case 1:
    1142             :                 case 0:
    1143         126 :                         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() ? 1 : 0, "s", &query,
    1144             :                                         &query_len)) {
    1145         126 :                                 ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink);
    1146             : 
    1147         126 :                                 bind_i = 1;
    1148         126 :                                 break;
    1149             :                         }
    1150           0 :                         return;
    1151             :         }
    1152             : 
    1153             :         /* open default transaction */
    1154         783 :         if (ib_link == NULL || FAILURE == _php_ibase_def_trans(ib_link, &trans)
    1155         522 :                         || FAILURE == _php_ibase_alloc_query(&ib_query, ib_link, trans, query, ib_link->dialect, trans_res)) {
    1156           3 :                 return;
    1157             :         }
    1158             : 
    1159             :         do {
    1160         258 :                 int bind_n = ZEND_NUM_ARGS() - bind_i,
    1161         258 :                     expected_n = ib_query.in_sqlda ? ib_query.in_sqlda->sqld : 0;
    1162             : 
    1163         258 :                 if (bind_n != expected_n) {
    1164           0 :                         php_error_docref(NULL, (bind_n < expected_n) ? E_WARNING : E_NOTICE,
    1165             :                                 "Statement expects %d arguments, %d given", expected_n, bind_n);
    1166           0 :                         if (bind_n < expected_n) {
    1167           0 :                                 break;
    1168             :                         }
    1169         258 :                 } else if (bind_n > 0) {
    1170          56 :                         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &bind_args, &bind_num) == FAILURE) {
    1171           0 :                                 return;
    1172             :                         }
    1173             :                 }
    1174             : 
    1175         516 :                 if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, &ib_query,
    1176         258 :                                 &bind_args[bind_i])) {
    1177           1 :                         break;
    1178             :                 }
    1179             : 
    1180         257 :                 if (result != NULL) { /* statement returns a result */
    1181          84 :                         result->type = QUERY_RESULT;
    1182             : 
    1183             :                         /* EXECUTE PROCEDURE returns only one row => statement can be released immediately */
    1184          84 :                         if (ib_query.statement_type != isc_info_sql_stmt_exec_procedure) {
    1185          84 :                                 ib_query.stmt = 0; /* keep stmt when free query */
    1186             :                         }
    1187          84 :                         RETVAL_RES(zend_register_resource(result, le_result));
    1188          84 :                         Z_TRY_ADDREF_P(return_value);
    1189             :                 }
    1190             :         } while (0);
    1191             : 
    1192         258 :         _php_ibase_free_query(&ib_query);
    1193             : 
    1194             : }
    1195             : /* }}} */
    1196             : 
    1197             : /* {{{ proto int ibase_affected_rows( [ resource link_identifier ] )
    1198             :    Returns the number of rows affected by the previous INSERT, UPDATE or DELETE statement */
    1199           3 : PHP_FUNCTION(ibase_affected_rows)
    1200             : {
    1201           3 :         ibase_trans *trans = NULL;
    1202             :         ibase_db_link *ib_link;
    1203           3 :         zval *arg = NULL;
    1204             : 
    1205           3 :         RESET_ERRMSG;
    1206             : 
    1207           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg) == FAILURE) {
    1208           0 :                 return;
    1209             :         }
    1210             : 
    1211           3 :         if (!arg) {
    1212           0 :                 ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink);
    1213           0 :                 if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
    1214           0 :                         RETURN_FALSE;
    1215             :                 }
    1216           0 :                 trans = ib_link->tr_list->trans;
    1217             :         } else {
    1218             :                 /* one id was passed, could be db or trans id */
    1219           3 :                 _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, arg, &ib_link, &trans);
    1220           3 :                 if (trans == NULL) {
    1221           3 :                         ib_link = (ibase_db_link *)zend_fetch_resource2_ex(arg, LE_LINK, le_link, le_plink);
    1222             : 
    1223           3 :                         if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
    1224           0 :                                 RETURN_FALSE;
    1225             :                         }
    1226           3 :                         trans = ib_link->tr_list->trans;
    1227             :                 }
    1228             :         }
    1229           3 :         RETURN_LONG(trans->affected_rows);
    1230             : }
    1231             : /* }}} */
    1232             : 
    1233             : /* {{{ proto int ibase_num_rows( resource result_identifier )
    1234             :    Return the number of rows that are available in a result */
    1235             : #if abies_0
    1236             : PHP_FUNCTION(ibase_num_rows)
    1237             : {
    1238             :         /**
    1239             :          * As this function relies on the InterBase API function isc_dsql_sql_info()
    1240             :          * which has a couple of limitations (which I hope will be fixed in future
    1241             :          * releases of Firebird), this function is fairly useless. I'm leaving it
    1242             :          * in place for people who can live with the limitations, which I only
    1243             :          * found out about after I had implemented it anyway.
    1244             :          *
    1245             :          * Currently, there's no way to determine how many rows can be fetched from
    1246             :          * a cursor. The only number that _can_ be determined is the number of rows
    1247             :          * that have already been pre-fetched by the client library.
    1248             :          * This implies the following:
    1249             :          * - num_rows() always returns zero before the first fetch;
    1250             :          * - num_rows() for SELECT ... FOR UPDATE is broken -> never returns a
    1251             :          *   higher number than the number of records fetched so far (no pre-fetch);
    1252             :          * - the result of num_rows() for other statements is merely a lower bound
    1253             :          *   on the number of records => calling ibase_num_rows() again after a couple
    1254             :          *   of fetches will most likely return a new (higher) figure for large result
    1255             :          *   sets.
    1256             :          */
    1257             : 
    1258             :         zval *result_arg;
    1259             :         ibase_result *ib_result;
    1260             :         static char info_count[] = {isc_info_sql_records};
    1261             :         char result[64];
    1262             : 
    1263             :         RESET_ERRMSG;
    1264             : 
    1265             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &result_arg) == FAILURE) {
    1266             :                 return;
    1267             :         }
    1268             : 
    1269             :         ib_result = (ibase_result *)zend_fetch_resource_ex(&result_arg, LE_RESULT, le_result);
    1270             : 
    1271             :         if (isc_dsql_sql_info(IB_STATUS, &ib_result->stmt, sizeof(info_count), info_count, sizeof(result), result)) {
    1272             :                 _php_ibase_error();
    1273             :                 RETURN_FALSE;
    1274             :         }
    1275             : 
    1276             :         if (result[0] == isc_info_sql_records) {
    1277             :                 unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
    1278             : 
    1279             :                 while (result[i] != isc_info_end && i < result_size) {
    1280             :                         short len = (short)isc_vax_integer(&result[i+1],2);
    1281             :                         if (result[i] == isc_info_req_select_count) {
    1282             :                                 RETURN_LONG(isc_vax_integer(&result[i+3],len));
    1283             :                         }
    1284             :                         i += len+3;
    1285             :                 }
    1286             :         }
    1287             : }
    1288             : #endif
    1289             : /* }}} */
    1290             : 
    1291        3579 : static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ */
    1292             :         int scale, int flag)
    1293             : {
    1294             :         static ISC_INT64 const scales[] = { 1, 10, 100, 1000,
    1295             :                 10000,
    1296             :                 100000,
    1297             :                 1000000,
    1298             :                 10000000,
    1299             :                 100000000,
    1300             :                 1000000000,
    1301             :                 LL_LIT(10000000000),
    1302             :                 LL_LIT(100000000000),
    1303             :                 LL_LIT(1000000000000),
    1304             :                 LL_LIT(10000000000000),
    1305             :                 LL_LIT(100000000000000),
    1306             :                 LL_LIT(1000000000000000),
    1307             :                 LL_LIT(10000000000000000),
    1308             :                 LL_LIT(100000000000000000),
    1309             :                 LL_LIT(1000000000000000000)
    1310             :         };
    1311             : 
    1312        3579 :         switch (type & ~1) {
    1313             :                 unsigned short l;
    1314             :                 zend_long n;
    1315             :                 char string_data[255];
    1316             :                 struct tm t;
    1317             :                 char *format;
    1318             : 
    1319             :                 case SQL_VARYING:
    1320          18 :                         len = ((IBVARY *) data)->vary_length;
    1321          18 :                         data = ((IBVARY *) data)->vary_string;
    1322             :                         /* no break */
    1323             :                 case SQL_TEXT:
    1324         182 :                         ZVAL_STRINGL(val, (char*)data, len);
    1325          91 :                         break;
    1326             :                 case SQL_SHORT:
    1327          46 :                         n = *(short *) data;
    1328          46 :                         goto _sql_long;
    1329             :                 case SQL_INT64:
    1330             : #if (SIZEOF_ZEND_LONG >= 8)
    1331          53 :                         n = *(zend_long *) data;
    1332          53 :                         goto _sql_long;
    1333             : #else
    1334             :                         if (scale == 0) {
    1335             :                                 l = slprintf(string_data, sizeof(string_data), "%" LL_MASK "d", *(ISC_INT64 *) data);
    1336             :                                 ZVAL_STRINGL(val,string_data,l);
    1337             :                         } else {
    1338             :                                 ISC_INT64 n = *(ISC_INT64 *) data, f = scales[-scale];
    1339             : 
    1340             :                                 if (n >= 0) {
    1341             :                                         l = slprintf(string_data, sizeof(string_data), "%" LL_MASK "d.%0*" LL_MASK "d", n / f, -scale, n % f);
    1342             :                                 } else if (n <= -f) {
    1343             :                                         l = slprintf(string_data, sizeof(string_data), "%" LL_MASK "d.%0*" LL_MASK "d", n / f, -scale, -n % f);
    1344             :                                  } else {
    1345             :                                         l = slprintf(string_data, sizeof(string_data), "-0.%0*" LL_MASK "d", -scale, -n % f);
    1346             :                                 }
    1347             :                                 ZVAL_STRINGL(val,string_data,l);
    1348             :                         }
    1349             :                         break;
    1350             : #endif
    1351             :                 case SQL_LONG:
    1352        3260 :                         n = *(ISC_LONG *) data;
    1353             :                 _sql_long:
    1354        3359 :                         if (scale == 0) {
    1355        3263 :                                 ZVAL_LONG(val,n);
    1356             :                         } else {
    1357          96 :                                 zend_long f = (zend_long) scales[-scale];
    1358             : 
    1359          96 :                                 if (n >= 0) {
    1360          66 :                                         l = slprintf(string_data, sizeof(string_data), ZEND_LONG_FMT ".%0*" ZEND_LONG_FMT_SPEC, n / f, -scale,  n % f);
    1361          30 :                                 } else if (n <= -f) {
    1362          30 :                                         l = slprintf(string_data, sizeof(string_data), ZEND_LONG_FMT ".%0*" ZEND_LONG_FMT_SPEC, n / f, -scale,  -n % f);
    1363             :                                 } else {
    1364           0 :                                         l = slprintf(string_data, sizeof(string_data), "-0.%0*" ZEND_LONG_FMT_SPEC, -scale, -n % f);
    1365             :                                 }
    1366         192 :                                 ZVAL_STRINGL(val, string_data, l);
    1367             :                         }
    1368        3359 :                         break;
    1369             :                 case SQL_FLOAT:
    1370          43 :                         ZVAL_DOUBLE(val, *(float *) data);
    1371          43 :                         break;
    1372             :                 case SQL_DOUBLE:
    1373          43 :                         ZVAL_DOUBLE(val, *(double *) data);
    1374          43 :                         break;
    1375             :                 case SQL_DATE: /* == case SQL_TIMESTAMP: */
    1376          43 :                         format = INI_STR("ibase.timestampformat");
    1377          43 :                         isc_decode_timestamp((ISC_TIMESTAMP *) data, &t);
    1378          43 :                         goto format_date_time;
    1379             :                 case SQL_TYPE_DATE:
    1380           0 :                         format = INI_STR("ibase.dateformat");
    1381           0 :                         isc_decode_sql_date((ISC_DATE *) data, &t);
    1382           0 :                         goto format_date_time;
    1383             :                 case SQL_TYPE_TIME:
    1384           0 :                         format = INI_STR("ibase.timeformat");
    1385           0 :                         isc_decode_sql_time((ISC_TIME *) data, &t);
    1386             : 
    1387             : format_date_time:
    1388             :                         /*
    1389             :                           XXX - Might have to remove this later - seems that isc_decode_date()
    1390             :                            always sets tm_isdst to 0, sometimes incorrectly (InterBase 6 bug?)
    1391             :                         */
    1392          43 :                         t.tm_isdst = -1;
    1393             : #if HAVE_TM_ZONE
    1394          43 :                         t.tm_zone = tzname[0];
    1395             : #endif
    1396          43 :                         if (flag & PHP_IBASE_UNIXTIME) {
    1397           0 :                                 ZVAL_LONG(val, mktime(&t));
    1398             :                         } else {
    1399             : #if HAVE_STRFTIME
    1400          43 :                                 l = strftime(string_data, sizeof(string_data), format, &t);
    1401             : #else
    1402             :                                 switch (type & ~1) {
    1403             :                                         default:
    1404             :                                                 l = slprintf(string_data, sizeof(string_data), "%02d/%02d/%4d %02d:%02d:%02d", t.tm_mon+1, t.tm_mday,
    1405             :                                                         t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec);
    1406             :                                                 break;
    1407             :                                         case SQL_TYPE_DATE:
    1408             :                                                 l = slprintf(string_data, sizeof(string_data), "%02d/%02d/%4d", t.tm_mon + 1, t.tm_mday, t.tm_year+1900);
    1409             :                                                 break;
    1410             :                                         case SQL_TYPE_TIME:
    1411             :                                                 l = slprintf(string_data, sizeof(string_data), "%02d:%02d:%02d", t.tm_hour, t.tm_min, t.tm_sec);
    1412             :                                                 break;
    1413             :                                 }
    1414             : #endif
    1415          86 :                                 ZVAL_STRINGL(val, string_data, l);
    1416             :                                 break;
    1417             :                         }
    1418             :         } /* switch (type) */
    1419        3579 :         return SUCCESS;
    1420             : }
    1421             : /* }}}  */
    1422             : 
    1423        3630 : static int _php_ibase_arr_zval(zval *ar_zval, char *data, zend_ulong data_size, /* {{{ */
    1424             :         ibase_array *ib_array, int dim, int flag)
    1425             : {
    1426             :         /**
    1427             :          * Create multidimension array - recursion function
    1428             :          */
    1429             :         int
    1430        3630 :                 u_bound = ib_array->ar_desc.array_desc_bounds[dim].array_bound_upper,
    1431        3630 :                 l_bound = ib_array->ar_desc.array_desc_bounds[dim].array_bound_lower,
    1432        3630 :                 dim_len = 1 + u_bound - l_bound;
    1433             :         unsigned short i;
    1434             : 
    1435        3630 :         if (dim < ib_array->ar_desc.array_desc_dimensions) { /* array again */
    1436         360 :                 zend_ulong slice_size = data_size / dim_len;
    1437             : 
    1438         360 :                 array_init(ar_zval);
    1439             : 
    1440        3960 :                 for (i = 0; i < dim_len; ++i) {
    1441             :                         zval slice_zval;
    1442             : 
    1443             :                         /* recursion here */
    1444        3600 :                         if (FAILURE == _php_ibase_arr_zval(&slice_zval, data, slice_size, ib_array, dim + 1,
    1445             :                                         flag)) {
    1446           0 :                                 return FAILURE;
    1447             :                         }
    1448        3600 :                         data += slice_size;
    1449             : 
    1450        3600 :                         add_index_zval(ar_zval, l_bound + i, &slice_zval);
    1451             :                 }
    1452             :         } else { /* data at last */
    1453             : 
    1454        6540 :                 if (FAILURE == _php_ibase_var_zval(ar_zval, data, ib_array->el_type,
    1455        6540 :                                 ib_array->ar_desc.array_desc_length, ib_array->ar_desc.array_desc_scale, flag)) {
    1456           0 :                         return FAILURE;
    1457             :                 }
    1458             : 
    1459             :                 /* fix for peculiar handling of VARCHAR arrays;
    1460             :                    truncate the field to the cstring length */
    1461        6510 :                 if (ib_array->ar_desc.array_desc_dtype == blr_varying ||
    1462        3240 :                         ib_array->ar_desc.array_desc_dtype == blr_varying2) {
    1463             : 
    1464          30 :                         Z_STRLEN_P(ar_zval) = strlen(Z_STRVAL_P(ar_zval));
    1465             :                 }
    1466             :         }
    1467        3630 :         return SUCCESS;
    1468             : }
    1469             : /* }}} */
    1470             : 
    1471         162 : static void _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int fetch_type) /* {{{ */
    1472             : {
    1473             :         zval *result_arg;
    1474         162 :         zend_long flag = 0;
    1475         162 :         zend_long i, array_cnt = 0;
    1476             :         ibase_result *ib_result;
    1477             : 
    1478         162 :         RESET_ERRMSG;
    1479             : 
    1480         162 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &result_arg, &flag)) {
    1481           1 :                 return;
    1482             :         }
    1483             : 
    1484         161 :         ib_result = (ibase_result *)zend_fetch_resource_ex(result_arg, LE_RESULT, le_result);
    1485             : 
    1486         161 :         if (ib_result->out_sqlda == NULL || !ib_result->has_more_rows) {
    1487          10 :                 RETURN_FALSE;
    1488             :         }
    1489             : 
    1490         151 :         if (ib_result->statement_type != isc_info_sql_stmt_exec_procedure) {
    1491         141 :                 if (isc_dsql_fetch(IB_STATUS, &ib_result->stmt, 1, ib_result->out_sqlda)) {
    1492          22 :                         ib_result->has_more_rows = 0;
    1493          22 :                         if (IB_STATUS[0] && IB_STATUS[1]) { /* error in fetch */
    1494           1 :                                 _php_ibase_error();
    1495             :                         }
    1496          22 :                         RETURN_FALSE;
    1497             :                 }
    1498             :         } else {
    1499          10 :                 ib_result->has_more_rows = 0;
    1500             :         }
    1501             : 
    1502         129 :         array_init(return_value);
    1503             : 
    1504         679 :         for (i = 0; i < ib_result->out_sqlda->sqld; ++i) {
    1505         550 :                 XSQLVAR *var = &ib_result->out_sqlda->sqlvar[i];
    1506         550 :                 char buf[METADATALENGTH+4], *alias = var->aliasname;
    1507             : 
    1508         550 :                 if (! (fetch_type & FETCH_ROW)) {
    1509         235 :                         int i = 0;
    1510         235 :                         char const *base = "FIELD"; /* use 'FIELD' if name is empty */
    1511             : 
    1512             :                         /**
    1513             :                         * Ensure no two columns have identical names:
    1514             :                         * keep generating new names until we find one that is unique.
    1515             :                         */
    1516         235 :                         switch (*alias) {
    1517             :                                 void *p;
    1518             : 
    1519             :                                 default:
    1520         235 :                                         i = 1;
    1521         235 :                                         base = alias;
    1522             : 
    1523         925 :                                         while ((p = zend_symtable_str_find_ptr(
    1524         345 :                                                         Z_ARRVAL_P(return_value), alias, strlen(alias))) != NULL) {
    1525             : 
    1526             :                                 case '\0':
    1527         110 :                                                 snprintf(alias = buf, sizeof(buf), "%s_%02d", base, i++);
    1528             :                                         }
    1529             :                         }
    1530             :                 }
    1531             : 
    1532         893 :                 if (((var->sqltype & 1) == 0) || *var->sqlind != -1) {
    1533             :                         zval result;
    1534             : 
    1535         343 :                         switch (var->sqltype & ~1) {
    1536             : 
    1537             :                                 default:
    1538         618 :                                         _php_ibase_var_zval(&result, var->sqldata, var->sqltype, var->sqllen,
    1539         309 :                                                 var->sqlscale, flag);
    1540         309 :                                         break;
    1541             :                                 case SQL_BLOB:
    1542           4 :                                         if (flag & PHP_IBASE_FETCH_BLOBS) { /* fetch blob contents into hash */
    1543             : 
    1544             :                                                 ibase_blob blob_handle;
    1545           2 :                                                 zend_ulong max_len = 0;
    1546             :                                                 static char bl_items[] = {isc_info_blob_total_length};
    1547             :                                                 char bl_info[20];
    1548             :                                                 unsigned short i;
    1549             : 
    1550           2 :                                                 blob_handle.bl_handle = 0;
    1551           2 :                                                 blob_handle.bl_qd = *(ISC_QUAD *) var->sqldata;
    1552             : 
    1553           2 :                                                 if (isc_open_blob(IB_STATUS, &ib_result->link->handle, &ib_result->trans->handle,
    1554             :                                                                 &blob_handle.bl_handle, &blob_handle.bl_qd)) {
    1555           0 :                                                         _php_ibase_error();
    1556           0 :                                                         goto _php_ibase_fetch_error;
    1557             :                                                 }
    1558             : 
    1559           2 :                                                 if (isc_blob_info(IB_STATUS, &blob_handle.bl_handle, sizeof(bl_items),
    1560             :                                                                 bl_items, sizeof(bl_info), bl_info)) {
    1561           0 :                                                         _php_ibase_error();
    1562           0 :                                                         goto _php_ibase_fetch_error;
    1563             :                                                 }
    1564             : 
    1565             :                                                 /* find total length of blob's data */
    1566           4 :                                                 for (i = 0; i < sizeof(bl_info); ) {
    1567             :                                                         unsigned short item_len;
    1568           2 :                                                         char item = bl_info[i++];
    1569             : 
    1570           2 :                                                         if (item == isc_info_end || item == isc_info_truncated ||
    1571             :                                                                 item == isc_info_error || i >= sizeof(bl_info)) {
    1572             : 
    1573           0 :                                                                 _php_ibase_module_error("Could not determine BLOB size (internal error)"
    1574             :                                                                         );
    1575           0 :                                                                 goto _php_ibase_fetch_error;
    1576             :                                                         }
    1577             : 
    1578           2 :                                                         item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2);
    1579             : 
    1580           2 :                                                         if (item == isc_info_blob_total_length) {
    1581           2 :                                                                 max_len = isc_vax_integer(&bl_info[i+2], item_len);
    1582           2 :                                                                 break;
    1583             :                                                         }
    1584           0 :                                                         i += item_len+2;
    1585             :                                                 }
    1586             : 
    1587           2 :                                                 if (max_len == 0) {
    1588           0 :                                                         ZVAL_STRING(&result, "");
    1589           2 :                                                 } else if (SUCCESS != _php_ibase_blob_get(&result, &blob_handle,
    1590             :                                                                 max_len)) {
    1591           0 :                                                         goto _php_ibase_fetch_error;
    1592             :                                                 }
    1593             : 
    1594           2 :                                                 if (isc_close_blob(IB_STATUS, &blob_handle.bl_handle)) {
    1595           0 :                                                         _php_ibase_error();
    1596           0 :                                                         goto _php_ibase_fetch_error;
    1597             :                                                 }
    1598             : 
    1599             :                                         } else { /* blob id only */
    1600           2 :                                                 ISC_QUAD bl_qd = *(ISC_QUAD *) var->sqldata;
    1601           2 :                                                 ZVAL_NEW_STR(&result, _php_ibase_quad_to_string(bl_qd));
    1602             :                                         }
    1603           4 :                                         break;
    1604             :                                 case SQL_ARRAY:
    1605          30 :                                         if (flag & PHP_IBASE_FETCH_ARRAYS) { /* array can be *huge* so only fetch if asked */
    1606          30 :                                                 ISC_QUAD ar_qd = *(ISC_QUAD *) var->sqldata;
    1607          30 :                                                 ibase_array *ib_array = &ib_result->out_array[array_cnt++];
    1608          30 :                                                 void *ar_data = emalloc(ib_array->ar_size);
    1609             : 
    1610          60 :                                                 if (isc_array_get_slice(IB_STATUS, &ib_result->link->handle,
    1611          30 :                                                                 &ib_result->trans->handle, &ar_qd, &ib_array->ar_desc,
    1612             :                                                                 ar_data, &ib_array->ar_size)) {
    1613           0 :                                                         _php_ibase_error();
    1614           0 :                                                         efree(ar_data);
    1615           0 :                                                         goto _php_ibase_fetch_error;
    1616             :                                                 }
    1617             : 
    1618          30 :                                                 if (FAILURE == _php_ibase_arr_zval(&result, ar_data, ib_array->ar_size, ib_array,
    1619             :                                                                 0, flag)) {
    1620           0 :                                                         efree(ar_data);
    1621           0 :                                                         goto _php_ibase_fetch_error;
    1622             :                                                 }
    1623          30 :                                                 efree(ar_data);
    1624             : 
    1625             :                                         } else { /* blob id only */
    1626           0 :                                                 ISC_QUAD ar_qd = *(ISC_QUAD *) var->sqldata;
    1627           0 :                                                 ZVAL_NEW_STR(&result, _php_ibase_quad_to_string(ar_qd));
    1628             :                                         }
    1629          30 :                                         break;
    1630             :                                 _php_ibase_fetch_error:
    1631             :                                         zval_dtor(&result);
    1632           0 :                                         RETURN_FALSE;
    1633             :                         } /* switch */
    1634             : 
    1635         343 :                         if (fetch_type & FETCH_ROW) {
    1636         108 :                                 add_index_zval(return_value, i, &result);
    1637             :                         } else {
    1638         235 :                                 add_assoc_zval(return_value, alias, &result);
    1639             :                         }
    1640             :                 } else {
    1641         207 :                         if (fetch_type & FETCH_ROW) {
    1642         207 :                                 add_index_null(return_value, i);
    1643             :                         } else {
    1644           0 :                                 add_assoc_null(return_value, alias);
    1645             :                         }
    1646             :                 }
    1647             :         } /* for field */
    1648             : }
    1649             : /* }}} */
    1650             : 
    1651             : /* {{{ proto array ibase_fetch_row(resource result [, int fetch_flags])
    1652             :    Fetch a row  from the results of a query */
    1653         137 : PHP_FUNCTION(ibase_fetch_row)
    1654             : {
    1655         137 :         _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, FETCH_ROW);
    1656         137 : }
    1657             : /* }}} */
    1658             : 
    1659             : /* {{{ proto array ibase_fetch_assoc(resource result [, int fetch_flags])
    1660             :    Fetch a row  from the results of a query */
    1661           5 : PHP_FUNCTION(ibase_fetch_assoc)
    1662             : {
    1663           5 :         _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, FETCH_ARRAY);
    1664           5 : }
    1665             : /* }}} */
    1666             : 
    1667             : /* {{{ proto object ibase_fetch_object(resource result [, int fetch_flags])
    1668             :    Fetch a object from the results of a query */
    1669          20 : PHP_FUNCTION(ibase_fetch_object)
    1670             : {
    1671          20 :         _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, FETCH_ARRAY);
    1672             : 
    1673          20 :         if (Z_TYPE_P(return_value) == IS_ARRAY) {
    1674          20 :                 convert_to_object(return_value);
    1675             :         }
    1676          20 : }
    1677             : /* }}} */
    1678             : 
    1679             : 
    1680             : /* {{{ proto bool ibase_name_result(resource result, string name)
    1681             :    Assign a name to a result for use with ... WHERE CURRENT OF <name> statements */
    1682           0 : PHP_FUNCTION(ibase_name_result)
    1683             : {
    1684             :         zval *result_arg;
    1685             :         char *name_arg;
    1686             :         size_t name_arg_len;
    1687             :         ibase_result *ib_result;
    1688             : 
    1689           0 :         RESET_ERRMSG;
    1690             : 
    1691           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &result_arg, &name_arg, &name_arg_len) == FAILURE) {
    1692           0 :                 return;
    1693             :         }
    1694             : 
    1695           0 :         ib_result = (ibase_result *)zend_fetch_resource_ex(result_arg, LE_RESULT, le_result);
    1696             : 
    1697           0 :         if (isc_dsql_set_cursor_name(IB_STATUS, &ib_result->stmt, name_arg, 0)) {
    1698           0 :                 _php_ibase_error();
    1699           0 :                 RETURN_FALSE;
    1700             :         }
    1701           0 :         RETURN_TRUE;
    1702             : }
    1703             : /* }}} */
    1704             : 
    1705             : 
    1706             : /* {{{ proto bool ibase_free_result(resource result)
    1707             :    Free the memory used by a result */
    1708          94 : PHP_FUNCTION(ibase_free_result)
    1709             : {
    1710             :         zval *result_arg;
    1711             :         ibase_result *ib_result;
    1712             : 
    1713          94 :         RESET_ERRMSG;
    1714             : 
    1715          94 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &result_arg) == FAILURE) {
    1716           0 :                 return;
    1717             :         }
    1718             : 
    1719          94 :         ib_result = (ibase_result *)zend_fetch_resource_ex(result_arg, LE_RESULT, le_result);
    1720          94 :         zend_list_delete(Z_RES_P(result_arg));
    1721          94 :         RETURN_TRUE;
    1722             : }
    1723             : /* }}} */
    1724             : 
    1725             : /* {{{ proto resource ibase_prepare(resource link_identifier[, string query [, resource trans_identifier ]])
    1726             :    Prepare a query for later execution */
    1727          12 : PHP_FUNCTION(ibase_prepare)
    1728             : {
    1729             :         zval *link_arg, *trans_arg;
    1730             :         ibase_db_link *ib_link;
    1731          12 :         ibase_trans *trans = NULL;
    1732             :         size_t query_len;
    1733          12 :         zend_resource *trans_res = NULL;
    1734             :         ibase_query *ib_query;
    1735             :         char *query;
    1736             : 
    1737          12 :         RESET_ERRMSG;
    1738             : 
    1739          12 :         if (ZEND_NUM_ARGS() == 1) {
    1740           7 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &query, &query_len) == FAILURE) {
    1741           0 :                         return;
    1742             :                 }
    1743           7 :                 ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink);
    1744           5 :         } else if (ZEND_NUM_ARGS() == 2) {
    1745           5 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &link_arg, &query, &query_len) == FAILURE) {
    1746           0 :                         return;
    1747             :                 }
    1748           5 :                 _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, link_arg, &ib_link, &trans);
    1749             : 
    1750           5 :                 if (trans != NULL) {
    1751           1 :                         trans_res = Z_RES_P(link_arg);
    1752             :                 }
    1753             :         } else {
    1754           0 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs", &link_arg, &trans_arg, &query, &query_len) == FAILURE) {
    1755           0 :                         return;
    1756             :                 }
    1757           0 :                 ib_link = (ibase_db_link *)zend_fetch_resource2_ex(link_arg, LE_LINK, le_link, le_plink);
    1758           0 :                 trans = (ibase_trans *)zend_fetch_resource_ex(trans_arg, LE_TRANS, le_trans);
    1759           0 :                 trans_res = Z_RES_P(trans_arg);
    1760             :         }
    1761             : 
    1762          12 :         if (FAILURE == _php_ibase_def_trans(ib_link, &trans)) {
    1763           0 :                 RETURN_FALSE;
    1764             :         }
    1765             : 
    1766          12 :         ib_query = (ibase_query *) emalloc(sizeof(ibase_query));
    1767             : 
    1768          12 :         if (FAILURE == _php_ibase_alloc_query(ib_query, ib_link, trans, query, ib_link->dialect, trans_res)) {
    1769           1 :                 efree(ib_query);
    1770           1 :                 RETURN_FALSE;
    1771             :         }
    1772          11 :         RETVAL_RES(zend_register_resource(ib_query, le_query));
    1773          11 :         Z_TRY_ADDREF_P(return_value);
    1774             : }
    1775             : /* }}} */
    1776             : 
    1777             : /* {{{ proto mixed ibase_execute(resource query [, mixed bind_arg [, mixed bind_arg [, ...]]])
    1778             :    Execute a previously prepared query */
    1779          27 : PHP_FUNCTION(ibase_execute)
    1780             : {
    1781          27 :         zval *query, *args = NULL;
    1782             :         ibase_query *ib_query;
    1783          27 :         ibase_result *result = NULL;
    1784          27 :         int bind_n = 0;
    1785             : 
    1786          27 :         RESET_ERRMSG;
    1787             : 
    1788          27 :         RETVAL_FALSE;
    1789             : 
    1790          27 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|r*", &query, &args, &bind_n)) {
    1791           0 :                 return;
    1792             :         }
    1793             : 
    1794          27 :         ib_query = (ibase_query *)zend_fetch_resource_ex(query, LE_QUERY, le_query);
    1795             : 
    1796             :         do {
    1797          27 :                 int     expected_n = ib_query->in_sqlda ? ib_query->in_sqlda->sqld : 0;
    1798             : 
    1799          27 :                 if (bind_n != expected_n) {
    1800           2 :                         php_error_docref(NULL, (bind_n < expected_n) ? E_WARNING : E_NOTICE,
    1801             :                                 "Statement expects %d arguments, %d given", expected_n, bind_n);
    1802             : 
    1803           2 :                         if (bind_n < expected_n) {
    1804           1 :                                 break;
    1805             :                         }
    1806             :                 }
    1807             : 
    1808             :                 /* Have we used this cursor before and it's still open (exec proc has no cursor) ? */
    1809          38 :                 if (ib_query->result_res != NULL
    1810          38 :                                 && ib_query->statement_type != isc_info_sql_stmt_exec_procedure) {
    1811             :                         IBDEBUG("Implicitly closing a cursor");
    1812             : 
    1813           3 :                         if (isc_dsql_free_statement(IB_STATUS, &ib_query->stmt, DSQL_close)) {
    1814           0 :                                 _php_ibase_error();
    1815           0 :                                 break;
    1816             :                         }
    1817           3 :                         zend_list_delete(ib_query->result_res);
    1818           3 :                         ib_query->result_res = NULL;
    1819             :                 }
    1820             : 
    1821          26 :                 if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, ib_query,
    1822             :                                 args)) {
    1823           0 :                     break;
    1824             :                 }
    1825             : 
    1826             :                 /* free the query if trans handle was released */
    1827          26 :                 if (ib_query->trans->handle == 0) {
    1828           0 :                         zend_list_delete(Z_RES_P(query));
    1829             :                 }
    1830             : 
    1831          26 :                 if (result != NULL) {
    1832             :                         zval *ret;
    1833             : 
    1834          15 :                         result->type = EXECUTE_RESULT;
    1835          15 :                         if (ib_query->statement_type == isc_info_sql_stmt_exec_procedure) {
    1836          10 :                                 result->stmt = 0;
    1837             :                         }
    1838             : 
    1839          15 :                         ret = zend_list_insert(result, le_result);
    1840          15 :                         ib_query->result_res = Z_RES_P(ret);
    1841          15 :                         ZVAL_COPY_VALUE(return_value, ret);
    1842          15 :                         Z_TRY_ADDREF_P(return_value);
    1843          15 :                         Z_TRY_ADDREF_P(return_value);
    1844             :                 }
    1845             :         } while (0);
    1846             : }
    1847             : /* }}} */
    1848             : 
    1849             : /* {{{ proto bool ibase_free_query(resource query)
    1850             :    Free memory used by a query */
    1851           7 : PHP_FUNCTION(ibase_free_query)
    1852             : {
    1853             :         zval *query_arg;
    1854             :         ibase_query *ib_query;
    1855             : 
    1856           7 :         RESET_ERRMSG;
    1857             : 
    1858           7 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &query_arg) == FAILURE) {
    1859           0 :                 return;
    1860             :         }
    1861             : 
    1862           7 :         ib_query = (ibase_query *)zend_fetch_resource_ex(query_arg, LE_QUERY, le_query);
    1863           7 :         if (!ib_query) {
    1864           2 :                 RETURN_FALSE;
    1865             :         }
    1866             : 
    1867           5 :         zend_list_close(Z_RES_P(query_arg));
    1868           5 :         RETURN_TRUE;
    1869             : }
    1870             : /* }}} */
    1871             : 
    1872             : /* {{{ proto int ibase_num_fields(resource query_result)
    1873             :    Get the number of fields in result */
    1874           3 : PHP_FUNCTION(ibase_num_fields)
    1875             : {
    1876             :         zval *result;
    1877             :         int type;
    1878             :         XSQLDA *sqlda;
    1879             : 
    1880           3 :         RESET_ERRMSG;
    1881             : 
    1882           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &result) == FAILURE) {
    1883           2 :                 return;
    1884             :         }
    1885             : 
    1886           1 :         type = Z_RES_P(result)->type;
    1887             : 
    1888           1 :         if (type == le_query) {
    1889             :                 ibase_query *ib_query;
    1890             : 
    1891           0 :                 ib_query = (ibase_query *)zend_fetch_resource_ex(result, LE_QUERY, le_query);
    1892           0 :                 sqlda = ib_query->out_sqlda;
    1893             :         } else {
    1894             :                 ibase_result *ib_result;
    1895             : 
    1896           1 :                 ib_result = (ibase_result *)zend_fetch_resource_ex(result, LE_RESULT, le_result);
    1897           1 :                 sqlda = ib_result->out_sqlda;
    1898             :         }
    1899             : 
    1900           1 :         if (sqlda == NULL) {
    1901           0 :                 RETURN_LONG(0);
    1902             :         } else {
    1903           1 :                 RETURN_LONG(sqlda->sqld);
    1904             :         }
    1905             : }
    1906             : /* }}} */
    1907             : 
    1908           1 : static void _php_ibase_field_info(zval *return_value, XSQLVAR *var) /* {{{ */
    1909             : {
    1910             :         unsigned short len;
    1911           1 :         char buf[16], *s = buf;
    1912             : 
    1913           1 :         array_init(return_value);
    1914             : 
    1915           1 :         add_index_stringl(return_value, 0, var->sqlname, var->sqlname_length);
    1916           1 :         add_assoc_stringl(return_value, "name", var->sqlname, var->sqlname_length);
    1917             : 
    1918           1 :         add_index_stringl(return_value, 1, var->aliasname, var->aliasname_length);
    1919           1 :         add_assoc_stringl(return_value, "alias", var->aliasname, var->aliasname_length);
    1920             : 
    1921           1 :         add_index_stringl(return_value, 2, var->relname, var->relname_length);
    1922           1 :         add_assoc_stringl(return_value, "relation", var->relname, var->relname_length);
    1923             : 
    1924           1 :         len = slprintf(buf, 16, "%d", var->sqllen);
    1925           1 :         add_index_stringl(return_value, 3, buf, len);
    1926           1 :         add_assoc_stringl(return_value, "length", buf, len);
    1927             : 
    1928           1 :         if (var->sqlscale < 0) {
    1929           0 :                 unsigned short precision = 0;
    1930             : 
    1931           0 :                 switch (var->sqltype & ~1) {
    1932             : 
    1933             :                         case SQL_SHORT:
    1934           0 :                                 precision = 4;
    1935           0 :                                 break;
    1936             :                         case SQL_LONG:
    1937           0 :                                 precision = 9;
    1938           0 :                                 break;
    1939             :                         case SQL_INT64:
    1940           0 :                                 precision = 18;
    1941             :                                 break;
    1942             :                 }
    1943           0 :                 len = slprintf(buf, 16, "NUMERIC(%d,%d)", precision, -var->sqlscale);
    1944           0 :                 add_index_stringl(return_value, 4, s, len);
    1945           0 :                 add_assoc_stringl(return_value, "type", s, len);
    1946             :         } else {
    1947           1 :                 switch (var->sqltype & ~1) {
    1948             :                         case SQL_TEXT:
    1949           0 :                                 s = "CHAR";
    1950           0 :                                 break;
    1951             :                         case SQL_VARYING:
    1952           0 :                                 s = "VARCHAR";
    1953           0 :                                 break;
    1954             :                         case SQL_SHORT:
    1955           0 :                                 s = "SMALLINT";
    1956           0 :                                 break;
    1957             :                         case SQL_LONG:
    1958           1 :                                 s = "INTEGER";
    1959           1 :                                 break;
    1960             :                         case SQL_FLOAT:
    1961           0 :                                 s = "FLOAT"; break;
    1962             :                         case SQL_DOUBLE:
    1963             :                         case SQL_D_FLOAT:
    1964           0 :                                 s = "DOUBLE PRECISION"; break;
    1965             :                         case SQL_INT64:
    1966           0 :                                 s = "BIGINT";
    1967           0 :                                 break;
    1968             :                         case SQL_TIMESTAMP:
    1969           0 :                                 s = "TIMESTAMP";
    1970           0 :                                 break;
    1971             :                         case SQL_TYPE_DATE:
    1972           0 :                                 s = "DATE";
    1973           0 :                                 break;
    1974             :                         case SQL_TYPE_TIME:
    1975           0 :                                 s = "TIME";
    1976           0 :                                 break;
    1977             :                         case SQL_BLOB:
    1978           0 :                                 s = "BLOB";
    1979           0 :                                 break;
    1980             :                         case SQL_ARRAY:
    1981           0 :                                 s = "ARRAY";
    1982           0 :                                 break;
    1983             :                                 /* FIXME: provide more detailed information about the field type, field size
    1984             :                                  * and array dimensions */
    1985             :                         case SQL_QUAD:
    1986           0 :                                 s = "QUAD";
    1987             :                                 break;
    1988             :                 }
    1989           1 :                 add_index_string(return_value, 4, s);
    1990           1 :                 add_assoc_string(return_value, "type", s);
    1991             :         }
    1992           1 : }
    1993             : /* }}} */
    1994             : 
    1995             : /* {{{ proto array ibase_field_info(resource query_result, int field_number)
    1996             :    Get information about a field */
    1997           0 : PHP_FUNCTION(ibase_field_info)
    1998             : {
    1999             :         zval *result_arg;
    2000             :         zend_long field_arg;
    2001             :         int type;
    2002             :         XSQLDA *sqlda;
    2003             : 
    2004           0 :         RESET_ERRMSG;
    2005             : 
    2006           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result_arg, &field_arg) == FAILURE) {
    2007           0 :                 return;
    2008             :         }
    2009             : 
    2010           0 :         type = Z_RES_P(result_arg)->type;
    2011             : 
    2012           0 :         if (type == le_query) {
    2013             :                 ibase_query *ib_query;
    2014             : 
    2015           0 :                 ib_query= (ibase_query *)zend_fetch_resource_ex(result_arg, LE_QUERY, le_query);
    2016           0 :                 sqlda = ib_query->out_sqlda;
    2017             :         } else {
    2018             :                 ibase_result *ib_result;
    2019             : 
    2020           0 :                 ib_result = (ibase_result *)zend_fetch_resource_ex(result_arg, LE_RESULT, le_result);
    2021           0 :                 sqlda = ib_result->out_sqlda;
    2022             :         }
    2023             : 
    2024           0 :         if (sqlda == NULL) {
    2025           0 :                 _php_ibase_module_error("Trying to get field info from a non-select query");
    2026           0 :                 RETURN_FALSE;
    2027             :         }
    2028             : 
    2029           0 :         if (field_arg < 0 || field_arg >= sqlda->sqld) {
    2030           0 :                 RETURN_FALSE;
    2031             :         }
    2032           0 :         _php_ibase_field_info(return_value, sqlda->sqlvar + field_arg);
    2033             : }
    2034             : /* }}} */
    2035             : 
    2036             : /* {{{ proto int ibase_num_params(resource query)
    2037             :    Get the number of params in a prepared query */
    2038           3 : PHP_FUNCTION(ibase_num_params)
    2039             : {
    2040             :         zval *result;
    2041             :         ibase_query *ib_query;
    2042             : 
    2043           3 :         RESET_ERRMSG;
    2044             : 
    2045           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &result) == FAILURE) {
    2046           2 :                 return;
    2047             :         }
    2048             : 
    2049           1 :         ib_query = (ibase_query *)zend_fetch_resource_ex(result, LE_QUERY, le_query);
    2050             : 
    2051           1 :         if (ib_query->in_sqlda == NULL) {
    2052           0 :                 RETURN_LONG(0);
    2053             :         } else {
    2054           1 :                 RETURN_LONG(ib_query->in_sqlda->sqld);
    2055             :         }
    2056             : }
    2057             : /* }}} */
    2058             : 
    2059             : /* {{{ proto array ibase_param_info(resource query, int field_number)
    2060             :    Get information about a parameter */
    2061           3 : PHP_FUNCTION(ibase_param_info)
    2062             : {
    2063             :         zval *result_arg;
    2064             :         zend_long field_arg;
    2065             :         ibase_query *ib_query;
    2066             : 
    2067           3 :         RESET_ERRMSG;
    2068             : 
    2069           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &result_arg, &field_arg) == FAILURE) {
    2070           1 :                 return;
    2071             :         }
    2072             : 
    2073           2 :         ib_query = (ibase_query *)zend_fetch_resource_ex(result_arg, LE_QUERY, le_query);
    2074             : 
    2075           2 :         if (ib_query->in_sqlda == NULL) {
    2076           0 :                 RETURN_FALSE;
    2077             :         }
    2078             : 
    2079           2 :         if (field_arg < 0 || field_arg >= ib_query->in_sqlda->sqld) {
    2080           1 :                 RETURN_FALSE;
    2081             :         }
    2082             : 
    2083           1 :         _php_ibase_field_info(return_value,ib_query->in_sqlda->sqlvar + field_arg);
    2084             : }
    2085             : /* }}} */
    2086             : 
    2087             : #endif /* HAVE_IBASE */
    2088             : 
    2089             : /*
    2090             :  * Local variables:
    2091             :  * tab-width: 4
    2092             :  * c-basic-offset: 4
    2093             :  * End:
    2094             :  * vim600: sw=4 ts=4 fdm=marker
    2095             :  * vim<600: sw=4 ts=4
    2096             :  */

Generated by: LCOV version 1.10

Generated at Sat, 09 Sep 2017 03:10:36 +0000 (14 days ago)

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