@@ -49,6 +49,7 @@ static void _php_db2_assign_options( void* handle, int type, char* opt_key, zval
4949static int _php_db2_parse_options ( zval * options , int type , void * handle TSRMLS_DC );
5050static void _php_db2_clear_conn_err_cache (TSRMLS_D );
5151static void _php_db2_clear_stmt_err_cache (TSRMLS_D );
52+ static void _php_db2_clear_exec_many_err_cache (void * handle );
5253static void _php_db2_set_decfloat_rounding_mode_client (void * handle TSRMLS_DC );
5354static char * _php_db2_instance_name ;
5455static int is_ios , is_zos ; /* 1 == TRUE; 0 == FALSE; */
@@ -402,6 +403,7 @@ static void _php_db2_free_result_struct(stmt_handle* handle)
402403 param_node * curr_ptr = NULL , * prev_ptr = NULL ;
403404
404405 if ( handle != NULL ) {
406+ _php_db2_clear_exec_many_err_cache (handle );
405407 /* Free param cache list */
406408 curr_ptr = handle -> head_cache_list ;
407409 prev_ptr = handle -> head_cache_list ;
@@ -1976,11 +1978,11 @@ static void _php_db2_clear_stmt_err_cache(TSRMLS_D)
19761978
19771979/* {{{ static void _php_db2_clear_exec_many_err_cache (TSRMLS_D)
19781980 */
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 )
19801982{
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 ;
19841986 }
19851987}
19861988/* }}} */
@@ -3703,6 +3705,9 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
37033705 }
37043706 if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
37053707 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+ }
37063711 if (Z_STRLEN_PP (bind_data ) < curr -> param_size + nullterm ) {
37073712 Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + nullterm );
37083713 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
37123717 if (curr -> param_type == DB2_PARAM_INOUT )
37133718#endif
37143719 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 ;
37173725 }
37183726#ifdef PASE /* help out PHP script trunc trailing chars -- LUW too? */
37193727 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
37233731 }
37243732#ifdef PASE /* zero length valueType = SQL_C_CHAR bad for i5/OS SQLBindParameter */
37253733 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+ }
37263737 Z_TYPE_PP (bind_data ) = IS_STRING ;
37273738 Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + nullterm );
37283739 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
37613772 case SQL_TYPE_TIMESTAMP :
37623773 if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
37633774 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+ }
37643778 if (Z_STRLEN_PP (bind_data ) < curr -> param_size + 1 ) {
37653779 Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + 1 );
37663780 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
37743788 }
37753789#ifdef PASE /* zero length valueType = SQL_C_CHAR bad for i5/OS SQLBindParameter */
37763790 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+ }
37773794 Z_STRVAL_PP (bind_data ) = erealloc (Z_STRVAL_PP (bind_data ), curr -> param_size + 1 );
37783795 memset (Z_STRVAL_PP (bind_data ), 0x20 , curr -> param_size + 1 );
37793796 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
37893806
37903807 /* copy data over from bind_data */
37913808 * (curr -> value ) = * * bind_data ;
3792- zval_copy_ctor (curr -> value );
3809+ zval_copy_ctor (curr -> value );
37933810 INIT_PZVAL (curr -> value );
37943811
37953812 /* 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
39323949
39333950 case IS_NULL :
39343951 Z_LVAL_P (curr -> value ) = SQL_NULL_DATA ;
3952+ Z_TYPE_P (curr -> value ) = IS_NULL ;
39353953 rc = SQLBindParameter (stmt_res -> hstmt , curr -> param_num ,
39363954 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 ));
39383956 if ( rc == SQL_ERROR ) {
39393957 _php_db2_check_sql_errors (stmt_res -> hstmt , SQL_HANDLE_STMT , rc , 1 , NULL , -1 , 1 TSRMLS_CC );
39403958 }
@@ -4056,6 +4074,41 @@ static int _php_db2_execute_helper(stmt_handle *stmt_res, zval **data, int bind_
40564074}
40574075/* }}} */
40584076
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+
40594112/* {{{ proto bool db2_execute(resource stmt [, array parameters_array])
40604113Executes a prepared SQL statement */
40614114PHP_FUNCTION (db2_execute )
@@ -4229,31 +4282,7 @@ PHP_FUNCTION(db2_execute)
42294282 /* cleanup dynamic bindings if present */
42304283 if ( bind_params == 1 ) {
42314284 /* 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 );
42574286 } else {
42584287#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
42594288 /* ADC - PHP changed general behavior 5.3+ */
@@ -6847,7 +6876,7 @@ PHP_FUNCTION( db2_execute_many )
68476876 error_msg_node * head_error_list = NULL ;
68486877
68496878 int rc ;
6850- int i = 0 ;
6879+ int i = 0 , j = 0 ;
68516880 SQLSMALLINT numOpts = 0 ;
68526881 int numOfRows = 0 ;
68536882 int numOfParam = 0 ;
@@ -6874,6 +6903,7 @@ PHP_FUNCTION( db2_execute_many )
68746903 }
68756904
68766905 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 );
68776907
68786908 /* Free any cursor that might have been allocated in a previous call to SQLExecute */
68796909 SQLFreeStmt ((SQLHSTMT )stmt_res -> hstmt , SQL_CLOSE );
@@ -6883,12 +6913,17 @@ PHP_FUNCTION( db2_execute_many )
68836913 rc = SQLNumParams ((SQLHSTMT )stmt_res -> hstmt , (SQLSMALLINT * )& numOpts );
68846914 data_type = (SQLSMALLINT * )ecalloc (numOpts , sizeof (SQLSMALLINT ));
68856915 array_data_type = (SQLSMALLINT * )ecalloc (numOpts , sizeof (SQLSMALLINT ));
6916+ for ( i = 0 ; i < numOpts ; i ++ ) {
6917+ array_data_type [i ] = -1 ;
6918+ }
68866919 if ( numOpts != 0 ) {
68876920 for ( i = 0 ; i < numOpts ; i ++ ) {
68886921 rc = SQLDescribeParam ((SQLHSTMT )stmt_res -> hstmt , i + 1 , (SQLSMALLINT * )(data_type + i ), & precision , (SQLSMALLINT * )& scale , (SQLSMALLINT * )& nullable );
68896922 if ( rc == SQL_ERROR ) {
68906923 php_error_docref (NULL TSRMLS_CC , E_WARNING , "Describe Param %d Failed" , i + 1 );
68916924 _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 );
68926927 RETURN_FALSE ;
68936928 }
68946929 _php_db2_build_list ( stmt_res , i + 1 , data_type [i ], precision , scale , nullable );
@@ -6900,7 +6935,7 @@ PHP_FUNCTION( db2_execute_many )
69006935 zend_hash_internal_pointer_reset (Z_ARRVAL_P (params ));
69016936 head_error_list = (error_msg_node * )ecalloc (1 , sizeof (error_msg_node ));
69026937 head_error_list -> next = NULL ;
6903- if ( numOfRows != 0 ) {
6938+ if ( numOfRows > 0 ) {
69046939 for ( i = 0 ; i < numOfRows ; i ++ ) {
69056940 param_node * curr = NULL ;
69066941 zval * * params_array = NULL ;
@@ -6944,18 +6979,88 @@ PHP_FUNCTION( db2_execute_many )
69446979 }
69456980
69466981 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 ) ) ) {
69486983 sprintf (error , "Value parameters array %d is not homogeneous with privious parameters array" , i + 1 );
69496984 _build_client_err_list (head_error_list , error );
69506985 err_count ++ ;
69516986 break ;
69526987 }
69536988 } 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+ }
69557021 }
69567022
69577023 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+ }
69597064 if ( rc == SQL_ERROR ) {
69607065 sprintf (error , "Binding Error1 : %s" , IBM_DB2_G (__php_stmt_err_msg ));
69617066 _build_client_err_list (head_error_list , error );
@@ -6965,12 +7070,20 @@ PHP_FUNCTION( db2_execute_many )
69657070 zend_hash_move_forward (Z_ARRVAL_PP (params_array ));
69667071 curr = curr -> next ;
69677072 }
6968-
69697073 if ( !chaining_start && (error [0 ] == '\0' ) ) {
69707074 /* Set statement attribute SQL_ATTR_CHAINING_BEGIN */
69717075 rc = _ibm_db_chaining_flag (stmt_res , SQL_ATTR_CHAINING_BEGIN , NULL , 0 TSRMLS_CC );
69727076 chaining_start = 1 ;
69737077 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 );
69747087 RETURN_FALSE ;
69757088 }
69767089 }
@@ -6980,12 +7093,18 @@ PHP_FUNCTION( db2_execute_many )
69807093 }
69817094 zend_hash_move_forward (Z_ARRVAL_P (params ));
69827095 }
7096+ } else {
7097+ RETURN_LONG (0 );
69837098 }
7099+ _free_param_cache_list (stmt_res );
7100+ efree (array_data_type );
7101+ efree (data_type );
69847102
69857103 /* Set statement attribute SQL_ATTR_CHAINING_END */
69867104 rc = SQL_ERROR ;
69877105 if ( chaining_start ) {
69887106 rc = _ibm_db_chaining_flag (stmt_res , SQL_ATTR_CHAINING_END , head_error_list -> next , err_count TSRMLS_CC );
7107+ efree (head_error_list );
69897108 }
69907109
69917110 if ( rc != SQL_SUCCESS || err_count != 0 ) {
0 commit comments