@@ -2223,18 +2223,88 @@ PHP_FUNCTION(ibase_param_info)
22232223 return ;
22242224 }
22252225
2226- ib_query = (ibase_query * )zend_fetch_resource_ex (result_arg , LE_QUERY , le_query );
22272226
2228- if (ib_query -> in_sqlda == NULL ) {
2229- RETURN_FALSE ;
2227+ static int _php_ibase_get_vars_count (ibase_query * ib_query )
2228+ {
2229+ int rv = FAILURE ;
2230+ // size_t buf_size = 128;
2231+ // ISC_UCHAR *buf = emalloc(buf_size);
2232+
2233+ ISC_UCHAR buf [64 ] = {0 };
2234+ size_t buf_size = sizeof (buf );
2235+
2236+ size_t pos ;
2237+
2238+ static ISC_UCHAR info_req [] = {
2239+ isc_info_sql_stmt_type ,
2240+ isc_info_sql_select ,
2241+ isc_info_sql_num_variables ,
2242+ isc_info_sql_bind ,
2243+ isc_info_sql_num_variables ,
2244+ };
2245+ // _php_ibase_parse_info_retry:
2246+ // memset(buf, 0, buf_size);
2247+ pos = 0 ;
2248+
2249+ // Assume buf will be tagged with `isc_info_truncated` and later in parsing
2250+ // we will catch that. Until `isc_info_truncated` is reached assume pos +=
2251+ // 2, etc are safe.
2252+ if (isc_dsql_sql_info (IB_STATUS , & ib_query -> stmt , sizeof (info_req ), (ISC_SCHAR * )info_req , buf_size , (ISC_SCHAR * )buf )) {
2253+ _php_ibase_error ();
2254+ goto _php_ibase_parse_info_fail ;
2255+ }
2256+
2257+ int ctx = 0 ;
2258+ while ((buf [pos ] != isc_info_end ) && (pos < buf_size ))
2259+ {
2260+ const ISC_UCHAR tag = buf [pos ++ ];
2261+ switch (tag ) {
2262+ case isc_info_sql_stmt_type : {
2263+ const ISC_USHORT size = (ISC_USHORT )isc_portable_integer (& buf [pos ], 2 ); pos += 2 ;
2264+ ib_query -> statement_type = (ISC_UCHAR )isc_portable_integer (& buf [pos ], size ); pos += size ;
2265+ } break ;
2266+ case isc_info_sql_select : ctx = 1 ; break ;
2267+ case isc_info_sql_bind : ctx = 2 ; break ;
2268+ case isc_info_sql_num_variables : {
2269+ const ISC_USHORT size = (ISC_USHORT )isc_portable_integer (& buf [pos ], 2 ); pos += 2 ;
2270+ const ISC_USHORT count = (ISC_USHORT )isc_portable_integer (& buf [pos ], size ); pos += size ;
2271+ if (ctx == 1 ) {
2272+ ib_query -> out_fields_count = count ;
2273+ } else if (ctx == 2 ) {
2274+ ib_query -> in_fields_count = count ;
2275+ } else {
2276+ fbp_fatal ("isc_info_sql_num_variables: unknown ctx %d" , ctx );
2277+ }
2278+ ctx = 0 ;
2279+ } break ;
2280+ case isc_info_truncated : {
2281+ fbp_notice ("BUG: sql_info buffer truncated, current capacity: %ld" , buf_size );
2282+ // Dynamic resize
2283+ // buf_size *= 2;
2284+ // buf = erealloc(buf, buf_size);
2285+ // goto _php_ibase_parse_info_retry;
2286+ } break ;
2287+ case isc_info_error : {
2288+ fbp_fatal ("sql_info buffer error, pos: %lu" , pos );
2289+ goto _php_ibase_parse_info_fail ;
2290+ } break ;
2291+ default : {
2292+ fbp_fatal ("BUG: unrecognized sql_info entry: %d, pos: %lu" , tag , pos );
2293+ goto _php_ibase_parse_info_fail ;
2294+ } break ;
2295+ }
22302296 }
22312297
2232- if (field_arg < 0 || field_arg >= ib_query -> in_sqlda -> sqld ) {
2233- RETURN_FALSE ;
2298+ if (buf [pos ] != isc_info_end ) {
2299+ fbp_fatal ("BUG: sql_info unexpected end of buffer at pos: %lu" , pos );
2300+ goto _php_ibase_parse_info_fail ;
22342301 }
22352302
2236- _php_ibase_field_info (return_value ,ib_query -> in_sqlda -> sqlvar + field_arg );
2303+ rv = SUCCESS ;
2304+
2305+ _php_ibase_parse_info_fail :
2306+ // efree(buf);
2307+ return rv ;
22372308}
2238- /* }}} */
22392309
22402310#endif /* HAVE_IBASE */
0 commit comments