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: 664 897 74.0 %
Date: 2014-07-21 Functions: 28 30 93.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:10 +0000 (8 days ago)

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