@@ -49,6 +49,7 @@ static void _php_db2_assign_options( void* handle, int type, char* opt_key, zval
49
49
static int _php_db2_parse_options ( zval * options , int type , void * handle TSRMLS_DC );
50
50
static void _php_db2_clear_conn_err_cache (TSRMLS_D );
51
51
static void _php_db2_clear_stmt_err_cache (TSRMLS_D );
52
+ static void _php_db2_clear_exec_many_err_cache (void * handle );
52
53
static void _php_db2_set_decfloat_rounding_mode_client (void * handle TSRMLS_DC );
53
54
static char * _php_db2_instance_name ;
54
55
static int is_ios , is_zos ; /* 1 == TRUE; 0 == FALSE; */
@@ -402,6 +403,7 @@ static void _php_db2_free_result_struct(stmt_handle* handle)
402
403
param_node * curr_ptr = NULL , * prev_ptr = NULL ;
403
404
404
405
if ( handle != NULL ) {
406
+ _php_db2_clear_exec_many_err_cache (handle );
405
407
/* Free param cache list */
406
408
curr_ptr = handle -> head_cache_list ;
407
409
prev_ptr = handle -> head_cache_list ;
@@ -1976,11 +1978,11 @@ static void _php_db2_clear_stmt_err_cache(TSRMLS_D)
1976
1978
1977
1979
/* {{{ static void _php_db2_clear_exec_many_err_cache (TSRMLS_D)
1978
1980
*/
1979
- static void _php_db2_clear_exec_many_err_cache ( stmt_handle * stmt )
1981
+ static void _php_db2_clear_exec_many_err_cache ( void * stmt )
1980
1982
{
1981
- if ( stmt -> exec_many_err_msg != NULL ) {
1982
- efree (stmt -> exec_many_err_msg );
1983
- stmt -> exec_many_err_msg = NULL ;
1983
+ if ( (( stmt_handle * ) stmt ) -> exec_many_err_msg != NULL ) {
1984
+ efree ((( stmt_handle * ) stmt ) -> exec_many_err_msg );
1985
+ (( stmt_handle * ) stmt ) -> exec_many_err_msg = NULL ;
1984
1986
}
1985
1987
}
1986
1988
/* }}} */
@@ -3703,6 +3705,9 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3703
3705
}
3704
3706
if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
3705
3707
int origlen = Z_STRLEN_PP (bind_data );
3708
+ if (IS_INTERNED ((* bind_data )-> value .str .val )) {
3709
+ Z_STRVAL_PP (bind_data ) = estrndup (Z_STRVAL_PP (bind_data ), origlen );
3710
+ }
3706
3711
if (Z_STRLEN_PP (bind_data ) < curr -> param_size + nullterm ) {
3707
3712
Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + nullterm );
3708
3713
if (Z_STRVAL_PP (bind_data ) == NULL ) {
@@ -3712,8 +3717,11 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3712
3717
if (curr -> param_type == DB2_PARAM_INOUT )
3713
3718
#endif
3714
3719
memset (Z_STRVAL_PP (bind_data )+ origlen ,0x20 , curr -> param_size - origlen );
3715
- if (nullterm ) Z_STRVAL_PP (bind_data )[origlen ] = '\0' ;
3716
- Z_STRLEN_PP (bind_data ) = curr -> param_size ;
3720
+ if (nullterm ) {
3721
+ Z_STRVAL_PP (bind_data )[origlen ] = '\0' ;
3722
+ Z_STRVAL_PP (bind_data )[curr -> param_size ] = '\0' ;
3723
+ }
3724
+ Z_STRLEN_PP (bind_data ) = curr -> param_size ;
3717
3725
}
3718
3726
#ifdef PASE /* help out PHP script trunc trailing chars -- LUW too? */
3719
3727
else if (Z_STRLEN_PP (bind_data ) > curr -> param_size ) {
@@ -3723,6 +3731,9 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3723
3731
}
3724
3732
#ifdef PASE /* zero length valueType = SQL_C_CHAR bad for i5/OS SQLBindParameter */
3725
3733
else if (Z_STRLEN_PP (bind_data ) == 0 ) {
3734
+ if (IS_INTERNED ((* bind_data )-> value .str .val )) {
3735
+ Z_STRVAL_PP (bind_data ) = estrndup (Z_STRVAL_PP (bind_data ), Z_STRLEN_PP (bind_data ));
3736
+ }
3726
3737
Z_TYPE_PP (bind_data ) = IS_STRING ;
3727
3738
Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + nullterm );
3728
3739
memset (Z_STRVAL_PP (bind_data ), 0x20 , curr -> param_size + nullterm );
@@ -3761,6 +3772,9 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3761
3772
case SQL_TYPE_TIMESTAMP :
3762
3773
if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
3763
3774
int origlen = Z_STRLEN_PP (bind_data );
3775
+ if (IS_INTERNED ((* bind_data )-> value .str .val )) {
3776
+ Z_STRVAL_PP (bind_data ) = estrndup (Z_STRVAL_PP (bind_data ), Z_STRLEN_PP (bind_data ));
3777
+ }
3764
3778
if (Z_STRLEN_PP (bind_data ) < curr -> param_size + 1 ) {
3765
3779
Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + 1 );
3766
3780
if (Z_STRVAL_PP (bind_data ) == NULL ) {
@@ -3774,6 +3788,9 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3774
3788
}
3775
3789
#ifdef PASE /* zero length valueType = SQL_C_CHAR bad for i5/OS SQLBindParameter */
3776
3790
else if (Z_STRLEN_PP (bind_data ) == 0 ) {
3791
+ if (IS_INTERNED ((* bind_data )-> value .str .val )) {
3792
+ Z_STRVAL_PP (bind_data ) = estrndup (Z_STRVAL_PP (bind_data ), Z_STRLEN_PP (bind_data ));
3793
+ }
3777
3794
Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + 1 );
3778
3795
memset (Z_STRVAL_PP (bind_data ), 0x20 , curr -> param_size + 1 );
3779
3796
Z_STRVAL_PP (bind_data )[curr -> param_size ] = '\0' ;
@@ -3789,7 +3806,7 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3789
3806
3790
3807
/* copy data over from bind_data */
3791
3808
* (curr -> value ) = * * bind_data ;
3792
- zval_copy_ctor (curr -> value );
3809
+ zval_copy_ctor (curr -> value );
3793
3810
INIT_PZVAL (curr -> value );
3794
3811
3795
3812
/* Have to use SQLBindFileToParam if PARAM is type DB2_PARAM_FILE */
@@ -3932,9 +3949,10 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
3932
3949
3933
3950
case IS_NULL :
3934
3951
Z_LVAL_P (curr -> value ) = SQL_NULL_DATA ;
3952
+ Z_TYPE_P (curr -> value ) = IS_NULL ;
3935
3953
rc = SQLBindParameter (stmt_res -> hstmt , curr -> param_num ,
3936
3954
curr -> param_type , SQL_C_DEFAULT , curr -> data_type , curr -> param_size ,
3937
- curr -> scale , & (curr -> value ), 0 , & ((curr -> value )-> value .lval ));
3955
+ curr -> scale , & (curr -> value ), 0 , ( SQLLEN * ) & ((curr -> value )-> value .lval ));
3938
3956
if ( rc == SQL_ERROR ) {
3939
3957
_php_db2_check_sql_errors (stmt_res -> hstmt , SQL_HANDLE_STMT , rc , 1 , NULL , -1 , 1 TSRMLS_CC );
3940
3958
}
@@ -4056,6 +4074,41 @@ static int _php_db2_execute_helper(stmt_handle *stmt_res, zval **data, int bind_
4056
4074
}
4057
4075
/* }}} */
4058
4076
4077
+ /* {{{ static void _free_param_cache_list(stmt_handle *stmt_res)
4078
+ */
4079
+ static void _free_param_cache_list (stmt_handle * stmt_res ) {
4080
+ param_node * prev_ptr = NULL , * curr_ptr = NULL ;
4081
+
4082
+ curr_ptr = stmt_res -> head_cache_list ;
4083
+ prev_ptr = stmt_res -> head_cache_list ;
4084
+ /* Free param cache list */
4085
+ while (curr_ptr != NULL ) {
4086
+ curr_ptr = curr_ptr -> next ;
4087
+
4088
+ /* Free Values */
4089
+ if (prev_ptr -> value != NULL ) {
4090
+ if ( Z_TYPE_P (prev_ptr -> value ) == IS_STRING ) {
4091
+ if ((prev_ptr -> value )-> value .str .val != NULL || (prev_ptr -> value )-> value .str .len != 0 ) {
4092
+ if (!IS_INTERNED ((prev_ptr -> value )-> value .str .val )) {
4093
+ efree ((prev_ptr -> value )-> value .str .val );
4094
+ }
4095
+ }
4096
+ }
4097
+
4098
+ if ( prev_ptr -> param_type != DB2_PARAM_OUT && prev_ptr -> param_type != DB2_PARAM_INOUT ){
4099
+ efree (prev_ptr -> value );
4100
+ }
4101
+ }
4102
+ efree (prev_ptr );
4103
+
4104
+ prev_ptr = curr_ptr ;
4105
+ }
4106
+
4107
+ stmt_res -> head_cache_list = NULL ;
4108
+ stmt_res -> num_params = 0 ;
4109
+ }
4110
+ /* }}} */
4111
+
4059
4112
/* {{{ proto bool db2_execute(resource stmt [, array parameters_array])
4060
4113
Executes a prepared SQL statement */
4061
4114
PHP_FUNCTION (db2_execute )
@@ -4229,31 +4282,7 @@ PHP_FUNCTION(db2_execute)
4229
4282
/* cleanup dynamic bindings if present */
4230
4283
if ( bind_params == 1 ) {
4231
4284
/* Free param cache list */
4232
- curr_ptr = stmt_res -> head_cache_list ;
4233
- prev_ptr = stmt_res -> head_cache_list ;
4234
-
4235
- while (curr_ptr != NULL ) {
4236
- curr_ptr = curr_ptr -> next ;
4237
-
4238
- /* Free Values */
4239
- if (prev_ptr -> value != NULL ) {
4240
- if ( Z_TYPE_P (prev_ptr -> value ) == IS_STRING ) {
4241
- if ((prev_ptr -> value )-> value .str .val != NULL || (prev_ptr -> value )-> value .str .len != 0 ) {
4242
- efree ((prev_ptr -> value )-> value .str .val );
4243
- }
4244
- }
4245
-
4246
- if ( prev_ptr -> param_type != DB2_PARAM_OUT && prev_ptr -> param_type != DB2_PARAM_INOUT ){
4247
- efree (prev_ptr -> value );
4248
- }
4249
- }
4250
- efree (prev_ptr );
4251
-
4252
- prev_ptr = curr_ptr ;
4253
- }
4254
-
4255
- stmt_res -> head_cache_list = NULL ;
4256
- stmt_res -> num_params = 0 ;
4285
+ _free_param_cache_list (stmt_res );
4257
4286
} else {
4258
4287
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
4259
4288
/* ADC - PHP changed general behavior 5.3+ */
@@ -6847,7 +6876,7 @@ PHP_FUNCTION( db2_execute_many )
6847
6876
error_msg_node * head_error_list = NULL ;
6848
6877
6849
6878
int rc ;
6850
- int i = 0 ;
6879
+ int i = 0 , j = 0 ;
6851
6880
SQLSMALLINT numOpts = 0 ;
6852
6881
int numOfRows = 0 ;
6853
6882
int numOfParam = 0 ;
@@ -6874,6 +6903,7 @@ PHP_FUNCTION( db2_execute_many )
6874
6903
}
6875
6904
6876
6905
ZEND_FETCH_RESOURCE (stmt_res , stmt_handle * , & stmt , stmt_id , "Statement Resource" , le_stmt_struct );
6906
+ _php_db2_clear_exec_many_err_cache (stmt_res );
6877
6907
6878
6908
/* Free any cursor that might have been allocated in a previous call to SQLExecute */
6879
6909
SQLFreeStmt ((SQLHSTMT )stmt_res -> hstmt , SQL_CLOSE );
@@ -6883,12 +6913,17 @@ PHP_FUNCTION( db2_execute_many )
6883
6913
rc = SQLNumParams ((SQLHSTMT )stmt_res -> hstmt , (SQLSMALLINT * )& numOpts );
6884
6914
data_type = (SQLSMALLINT * )ecalloc (numOpts , sizeof (SQLSMALLINT ));
6885
6915
array_data_type = (SQLSMALLINT * )ecalloc (numOpts , sizeof (SQLSMALLINT ));
6916
+ for ( i = 0 ; i < numOpts ; i ++ ) {
6917
+ array_data_type [i ] = -1 ;
6918
+ }
6886
6919
if ( numOpts != 0 ) {
6887
6920
for ( i = 0 ; i < numOpts ; i ++ ) {
6888
6921
rc = SQLDescribeParam ((SQLHSTMT )stmt_res -> hstmt , i + 1 , (SQLSMALLINT * )(data_type + i ), & precision , (SQLSMALLINT * )& scale , (SQLSMALLINT * )& nullable );
6889
6922
if ( rc == SQL_ERROR ) {
6890
6923
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Describe Param %d Failed" , i + 1 );
6891
6924
_php_db2_check_sql_errors ((SQLHSTMT )stmt_res -> hstmt , SQL_HANDLE_STMT , rc , 1 , NULL , -1 , 1 TSRMLS_CC );
6925
+ efree (array_data_type );
6926
+ efree (data_type );
6892
6927
RETURN_FALSE ;
6893
6928
}
6894
6929
_php_db2_build_list ( stmt_res , i + 1 , data_type [i ], precision , scale , nullable );
@@ -6900,7 +6935,7 @@ PHP_FUNCTION( db2_execute_many )
6900
6935
zend_hash_internal_pointer_reset (Z_ARRVAL_P (params ));
6901
6936
head_error_list = (error_msg_node * )ecalloc (1 , sizeof (error_msg_node ));
6902
6937
head_error_list -> next = NULL ;
6903
- if ( numOfRows != 0 ) {
6938
+ if ( numOfRows > 0 ) {
6904
6939
for ( i = 0 ; i < numOfRows ; i ++ ) {
6905
6940
param_node * curr = NULL ;
6906
6941
zval * * params_array = NULL ;
@@ -6944,18 +6979,88 @@ PHP_FUNCTION( db2_execute_many )
6944
6979
}
6945
6980
6946
6981
if ( chaining_start ) {
6947
- if ( array_data_type [curr -> param_num - 1 ] != Z_TYPE_PP (data ) ) {
6982
+ if ( ( Z_TYPE_PP ( data ) != IS_NULL ) && ( array_data_type [curr -> param_num - 1 ] != Z_TYPE_PP (data ) ) ) {
6948
6983
sprintf (error , "Value parameters array %d is not homogeneous with privious parameters array" , i + 1 );
6949
6984
_build_client_err_list (head_error_list , error );
6950
6985
err_count ++ ;
6951
6986
break ;
6952
6987
}
6953
6988
} else {
6954
- array_data_type [curr -> param_num - 1 ] = Z_TYPE_PP (data );
6989
+ if ( Z_TYPE_PP (data ) != IS_NULL ) {
6990
+ array_data_type [curr -> param_num - 1 ] = Z_TYPE_PP (data );
6991
+ j ++ ;
6992
+ } else {
6993
+ int tmp_j = 0 ;
6994
+ zend_hash_move_forward (Z_ARRVAL_P (params ));
6995
+ while ( zend_hash_get_current_data (Z_ARRVAL_P (params ), (void * * )& params_array ) == SUCCESS ) {
6996
+ zend_hash_internal_pointer_reset (Z_ARRVAL_PP (params_array ));
6997
+ for ( tmp_j = 0 ; tmp_j <= j ; tmp_j ++ ) {
6998
+ zend_hash_move_forward (Z_ARRVAL_PP (params_array ));
6999
+ }
7000
+ zend_hash_get_current_data (Z_ARRVAL_PP (params_array ), (void * * )& data );
7001
+ if ( ( data != NULL ) && ( Z_TYPE_PP (data ) != IS_NULL ) ) {
7002
+ array_data_type [curr -> param_num - 1 ] = Z_TYPE_PP (data );
7003
+ j ++ ;
7004
+ break ;
7005
+ } else {
7006
+ zend_hash_move_forward (Z_ARRVAL_P (params ));
7007
+ continue ;
7008
+ }
7009
+ }
7010
+ if ( array_data_type [curr -> param_num - 1 ] == -1 ) {
7011
+ array_data_type [curr -> param_num - 1 ] = IS_NULL ;
7012
+ }
7013
+ zend_hash_internal_pointer_reset (Z_ARRVAL_P (params ));
7014
+ zend_hash_get_current_data (Z_ARRVAL_P (params ), (void * * )& params_array );
7015
+ zend_hash_internal_pointer_reset (Z_ARRVAL_PP (params_array ));
7016
+ for ( tmp_j = 0 ; tmp_j < j ; tmp_j ++ ) {
7017
+ zend_hash_move_forward (Z_ARRVAL_PP (params_array ));
7018
+ }
7019
+ zend_hash_get_current_data (Z_ARRVAL_PP (params_array ), (void * * )& data );
7020
+ }
6955
7021
}
6956
7022
6957
7023
curr -> data_type = data_type [curr -> param_num - 1 ];
6958
- rc = _php_db2_bind_data (stmt_res , curr , data TSRMLS_CC );
7024
+ if ( Z_TYPE_PP (data ) != IS_NULL ) {
7025
+ rc = _php_db2_bind_data (stmt_res , curr , data TSRMLS_CC );
7026
+ } else {
7027
+ SQLSMALLINT valueType = 0 ;
7028
+ switch ( array_data_type [curr -> param_num - 1 ] ) {
7029
+ case IS_BOOL :
7030
+ case IS_LONG :
7031
+ if ( curr -> data_type == SQL_BIGINT ) {
7032
+ valueType = SQL_C_CHAR ;
7033
+ } else {
7034
+ valueType = SQL_C_LONG ;
7035
+ }
7036
+ break ;
7037
+ case IS_DOUBLE :
7038
+ valueType = SQL_C_DOUBLE ;
7039
+ break ;
7040
+ case IS_STRING :
7041
+ switch ( curr -> data_type ) {
7042
+ case SQL_BLOB :
7043
+ case SQL_BINARY :
7044
+ case SQL_LONGVARBINARY :
7045
+ case SQL_VARBINARY :
7046
+ case SQL_XML :
7047
+ valueType = SQL_C_BINARY ;
7048
+ break ;
7049
+ case SQL_CLOB :
7050
+ case SQL_DBCLOB :
7051
+ case SQL_VARCHAR :
7052
+ case SQL_BIGINT :
7053
+ default :
7054
+ valueType = SQL_C_CHAR ;
7055
+ }
7056
+ break ;
7057
+ case IS_NULL :
7058
+ valueType = SQL_C_DEFAULT ;
7059
+ }
7060
+ Z_LVAL_P (curr -> value ) = SQL_NULL_DATA ;
7061
+ Z_TYPE_P (curr -> value ) = IS_NULL ;
7062
+ rc = SQLBindParameter (stmt_res -> hstmt , curr -> param_num , curr -> param_type , valueType , curr -> data_type , curr -> param_size , curr -> scale , & (curr -> value ), 0 , (SQLLEN * )& ((curr -> value )-> value .lval ));
7063
+ }
6959
7064
if ( rc == SQL_ERROR ) {
6960
7065
sprintf (error , "Binding Error1 : %s" , IBM_DB2_G (__php_stmt_err_msg ));
6961
7066
_build_client_err_list (head_error_list , error );
@@ -6965,12 +7070,20 @@ PHP_FUNCTION( db2_execute_many )
6965
7070
zend_hash_move_forward (Z_ARRVAL_PP (params_array ));
6966
7071
curr = curr -> next ;
6967
7072
}
6968
-
6969
7073
if ( !chaining_start && (error [0 ] == '\0' ) ) {
6970
7074
/* Set statement attribute SQL_ATTR_CHAINING_BEGIN */
6971
7075
rc = _ibm_db_chaining_flag (stmt_res , SQL_ATTR_CHAINING_BEGIN , NULL , 0 TSRMLS_CC );
6972
7076
chaining_start = 1 ;
6973
7077
if ( rc != SQL_SUCCESS ) {
7078
+ error_msg_node * tmp_err_node ;
7079
+ while ( head_error_list != NULL ) {
7080
+ tmp_err_node = head_error_list ;
7081
+ head_error_list = head_error_list -> next ;
7082
+ efree (tmp_err_node );
7083
+ }
7084
+ _free_param_cache_list (stmt_res );
7085
+ efree (array_data_type );
7086
+ efree (data_type );
6974
7087
RETURN_FALSE ;
6975
7088
}
6976
7089
}
@@ -6980,12 +7093,18 @@ PHP_FUNCTION( db2_execute_many )
6980
7093
}
6981
7094
zend_hash_move_forward (Z_ARRVAL_P (params ));
6982
7095
}
7096
+ } else {
7097
+ RETURN_LONG (0 );
6983
7098
}
7099
+ _free_param_cache_list (stmt_res );
7100
+ efree (array_data_type );
7101
+ efree (data_type );
6984
7102
6985
7103
/* Set statement attribute SQL_ATTR_CHAINING_END */
6986
7104
rc = SQL_ERROR ;
6987
7105
if ( chaining_start ) {
6988
7106
rc = _ibm_db_chaining_flag (stmt_res , SQL_ATTR_CHAINING_END , head_error_list -> next , err_count TSRMLS_CC );
7107
+ efree (head_error_list );
6989
7108
}
6990
7109
6991
7110
if ( rc != SQL_SUCCESS || err_count != 0 ) {
0 commit comments