11/*
22 +----------------------------------------------------------------------+
3- | Copyright IBM Corporation 2005-2008 |
3+ | Copyright IBM Corporation 2005-2014 |
44 +----------------------------------------------------------------------+
55 | |
66 | Licensed under the Apache License, Version 2.0 (the "License"); you |
@@ -119,6 +119,7 @@ typedef struct _conn_handle_struct {
119119 SQLSMALLINT errormsg_recno_tracker ;
120120 int flag_pconnect ; /* Indicates that this connection is persistent */
121121 int flag_transaction ; /* Indicates that transaction is commited */
122+ int expansion_factor ; /* Maximum expected expansion factor for the length of mixed character data when converted to the application code page from datavase code page */
122123} conn_handle ;
123124
124125typedef union {
@@ -174,6 +175,8 @@ typedef struct _stmt_handle_struct {
174175 db2_result_set_info * column_info ;
175176 db2_row_type * row_data ;
176177 char * exec_many_err_msg ;
178+ int expansion_factor ; /* maximum expected expansion factor for the length of mixed character data */
179+ /* when converted to the application code page from the database code page*/
177180} stmt_handle ;
178181
179182
@@ -496,6 +499,8 @@ static stmt_handle *_db2_new_stmt_struct(conn_handle* conn_res)
496499 stmt_res -> s_i5_sys_naming = conn_res -> c_i5_sys_naming ;
497500#endif /* PASE */
498501
502+ stmt_res -> expansion_factor = conn_res -> expansion_factor ;
503+
499504 stmt_res -> head_cache_list = NULL ;
500505 stmt_res -> current_node = NULL ;
501506
@@ -543,12 +548,12 @@ PHP_MINIT_FUNCTION(ibm_db2)
543548#endif
544549
545550 ZEND_INIT_MODULE_GLOBALS (ibm_db2 , php_ibm_db2_init_globals , NULL );
551+ REGISTER_LONG_CONSTANT ("DB2_I5_NAMING_ON" , SQL_TRUE , CONST_CS | CONST_PERSISTENT );
552+ REGISTER_LONG_CONSTANT ("DB2_I5_NAMING_OFF" , SQL_FALSE , CONST_CS | CONST_PERSISTENT );
546553
547554#ifdef PASE /* i5OS db2_setoptions */
548555 REGISTER_LONG_CONSTANT ("DB2_I5_FETCH_ON" , SQL_TRUE , CONST_CS | CONST_PERSISTENT );
549556 REGISTER_LONG_CONSTANT ("DB2_I5_FETCH_OFF" , SQL_FALSE , CONST_CS | CONST_PERSISTENT );
550- REGISTER_LONG_CONSTANT ("DB2_I5_NAMING_ON" , SQL_TRUE , CONST_CS | CONST_PERSISTENT );
551- REGISTER_LONG_CONSTANT ("DB2_I5_NAMING_OFF" , SQL_FALSE , CONST_CS | CONST_PERSISTENT );
552557 REGISTER_LONG_CONSTANT ("DB2_I5_JOB_SORT_ON" , SQL_TRUE , CONST_CS | CONST_PERSISTENT );
553558 REGISTER_LONG_CONSTANT ("DB2_I5_JOB_SORT_OFF" , SQL_FALSE , CONST_CS | CONST_PERSISTENT );
554559 REGISTER_LONG_CONSTANT ("DB2_I5_DBCS_ALLOC_ON" , SQL_TRUE , CONST_CS | CONST_PERSISTENT );
@@ -682,7 +687,8 @@ static int _php_ibm_db2_conn (zend_rsrc_list_entry *le TSRMLS_DC)
682687PHP_RSHUTDOWN_FUNCTION (ibm_db2 )
683688{
684689 zend_hash_apply (& EG (persistent_list ), (apply_func_t ) _php_ibm_db2_conn TSRMLS_CC );
685-
690+ _php_db2_clear_conn_err_cache (TSRMLS_C );
691+ _php_db2_clear_stmt_err_cache (TSRMLS_C );
686692 return SUCCESS ;
687693}
688694/* }}} */
@@ -1277,6 +1283,28 @@ static void _php_db2_assign_options( void *handle, int type, char *opt_key, zval
12771283 default :
12781284 php_error_docref (NULL TSRMLS_CC , E_WARNING , "DB2_ATTR_CASE attribute can only be set on connection or statement resources" );
12791285 }
1286+ } else if (!STRCASECMP (opt_key , "i5_naming" )) {
1287+ /* i5_naming - SQL_ATTR_DBC_SYS_NAMING
1288+ DB2_I5_NAMING_ON value turns on DB2 UDB CLI iSeries system naming mode. Files are qualified using the slash (/) delimiter. Unqualified files are resolved using the library list for the job..
1289+ DB2_I5_NAMING_OFF value turns off DB2 UDB CLI default naming mode, which is SQL naming. Files are qualified using the period (.) delimiter. Unqualified files are resolved using either the default library or the current user ID.
1290+ */
1291+ pvParam = option_num ;
1292+ switch (option_num ) {
1293+ case DB2_I5_NAMING_ON :
1294+ case DB2_I5_NAMING_OFF :
1295+ #ifdef PASE
1296+ ((conn_handle * )handle )-> c_i5_sys_naming = option_num ;
1297+ rc = SQLSetConnectAttr ((SQLHDBC )((conn_handle * )handle )-> hdbc , SQL_ATTR_DBC_SYS_NAMING , (SQLPOINTER )& pvParam , SQL_NTS );
1298+ #else
1299+ rc = SQLSetConnectAttr ((SQLHDBC )((conn_handle * )handle )-> hdbc , SQL_ATTR_DBC_SYS_NAMING , (SQLPOINTER )pvParam , SQL_NTS );
1300+ #endif
1301+ if ( rc == SQL_ERROR ) {
1302+ _php_db2_check_sql_errors ((SQLHSTMT )((conn_handle * )handle )-> hdbc , SQL_HANDLE_DBC , rc , 1 , NULL , -1 , 1 TSRMLS_CC );
1303+ }
1304+ break ;
1305+ default :
1306+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "i5_naming attribute must be DB2_I5_NAMING_ON or DB2_I5_NAMING_OFF)" );
1307+ }
12801308#ifdef PASE /* i5/OS new set options */
12811309 } else if (!STRCASECMP (opt_key , "i5_lib" )) {
12821310 /* i5_lib - SQL_ATTR_DBC_DEFAULT_LIB
@@ -1320,24 +1348,6 @@ static void _php_db2_assign_options( void *handle, int type, char *opt_key, zval
13201348 } else {
13211349 php_error_docref (NULL TSRMLS_CC , E_WARNING , "i5_libl missing library list" );
13221350 }
1323- } else if (!STRCASECMP (opt_key , "i5_naming" )) {
1324- /* i5_naming - SQL_ATTR_DBC_SYS_NAMING
1325- DB2_I5_NAMING_ON value turns on DB2 UDB CLI iSeries system naming mode. Files are qualified using the slash (/) delimiter. Unqualified files are resolved using the library list for the job..
1326- DB2_I5_NAMING_OFF value turns off DB2 UDB CLI default naming mode, which is SQL naming. Files are qualified using the period (.) delimiter. Unqualified files are resolved using either the default library or the current user ID.
1327- */
1328- pvParam = option_num ;
1329- switch (option_num ) {
1330- case DB2_I5_NAMING_ON :
1331- case DB2_I5_NAMING_OFF :
1332- ((conn_handle * )handle )-> c_i5_sys_naming = option_num ;
1333- rc = SQLSetConnectAttr ((SQLHDBC )((conn_handle * )handle )-> hdbc , SQL_ATTR_DBC_SYS_NAMING , (SQLPOINTER )& pvParam , SQL_NTS );
1334- if ( rc == SQL_ERROR ) {
1335- _php_db2_check_sql_errors ((SQLHSTMT )((conn_handle * )handle )-> hdbc , SQL_HANDLE_DBC , rc , 1 , NULL , -1 , 1 TSRMLS_CC );
1336- }
1337- break ;
1338- default :
1339- php_error_docref (NULL TSRMLS_CC , E_WARNING , "i5_naming (DB2_I5_NAMING_ON , DB2_I5_NAMING_OFF )");
1340- }
13411351 } else if (!STRCASECMP (opt_key , "i5_job_sort" )) {
13421352 /* i5_job_sort - SQL_ATTR_JOB_SORT_SEQUENCE (conn is hidden 10046)
13431353 DB2_I5_JOB_SORT_ON value turns on DB2 UDB CLI job sort mode.
@@ -1777,7 +1787,12 @@ static int _php_db2_bind_column_helper(stmt_handle *stmt_res TSRMLS_DC)
17771787 case SQL_LONGVARGRAPHIC :
17781788#endif /* PASE */
17791789 target_type = SQL_C_CHAR ;
1780- in_length = stmt_res -> column_info [i ].size + 1 ;
1790+ /* Multiply the size by expansion factor to handle cases where client and server code page are different*/
1791+ if (stmt_res -> expansion_factor > 1 ){
1792+ in_length = stmt_res -> column_info [i ].size * stmt_res -> expansion_factor + 1 ;
1793+ } else {
1794+ in_length = stmt_res -> column_info [i ].size + 1 ;
1795+ }
17811796 row_data -> str_val = (SQLCHAR * )ecalloc (1 , in_length );
17821797
17831798 rc = SQLBindCol ((SQLHSTMT )stmt_res -> hstmt , (SQLUSMALLINT )(i + 1 ),
@@ -2013,6 +2028,7 @@ static int _php_db2_connect_helper( INTERNAL_FUNCTION_PARAMETERS, conn_handle **
20132028 int conn_null = 0 ;
20142029 int conn_was_pclose = 0 ;
20152030#endif /* PASE */
2031+ struct sqlca sqlca ;
20162032
20172033 conn_alive = 1 ;
20182034
@@ -2179,6 +2195,20 @@ static int _php_db2_connect_helper( INTERNAL_FUNCTION_PARAMETERS, conn_handle **
21792195 break ;
21802196 }
21812197
2198+ /* Get maximum expected expansion factor for the length of mixed character data when converted to the */
2199+ /* application code page from the database code page*/
2200+ rc = SQLGetSQLCA ((SQLHENV ) conn_res -> henv , (SQLHDBC ) conn_res -> hdbc , SQL_NULL_HSTMT , & sqlca );
2201+
2202+ if ( rc == SQL_ERROR ) {
2203+ _php_db2_check_sql_errors (conn_res -> hdbc , SQL_HANDLE_DBC , rc , 1 , NULL , -1 , 1 TSRMLS_CC );
2204+ SQLDisconnect ((SQLHDBC )conn_res -> hdbc );
2205+ SQLFreeHandle ( SQL_HANDLE_DBC , conn_res -> hdbc );
2206+ SQLFreeHandle (SQL_HANDLE_ENV , conn_res -> henv );
2207+ break ;
2208+ } else {
2209+ conn_res -> expansion_factor = sqlca .sqlerrd [1 ];
2210+ }
2211+
21822212 /* Get the AUTOCOMMIT state from the CLI driver as cli driver could have changed autocommit status based on it's
21832213 * precedence */
21842214 rc = SQLGetConnectAttr ((SQLHDBC )conn_res -> hdbc , SQL_ATTR_AUTOCOMMIT ,(SQLPOINTER )(& conn_res -> auto_commit ), 0 , NULL );
@@ -3649,6 +3679,7 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
36493679 SQLSMALLINT valueType ;
36503680 SQLPOINTER paramValuePtr ;
36513681 int nullterm = 0 ;
3682+ int origlen = -1 ;
36523683
36533684 /* Clean old zval value and create a new one */
36543685 if ( curr -> value != 0 && curr -> param_type != DB2_PARAM_OUT && curr -> param_type != DB2_PARAM_INOUT )
@@ -3704,7 +3735,7 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
37043735 convert_to_string (* bind_data );
37053736 }
37063737 if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
3707- int origlen = Z_STRLEN_PP (bind_data );
3738+ origlen = Z_STRLEN_PP (bind_data );
37083739 if (IS_INTERNED ((* bind_data )-> value .str .val )) {
37093740 Z_STRVAL_PP (bind_data ) = estrndup (Z_STRVAL_PP (bind_data ), origlen );
37103741 }
@@ -3856,7 +3887,11 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
38563887 case SQL_CLOB :
38573888 case SQL_DBCLOB :
38583889 if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
3859- curr -> bind_indicator = (curr -> value )-> value .str .len ;
3890+ if (origlen != -1 ) {
3891+ curr -> bind_indicator = origlen ;
3892+ } else {
3893+ curr -> bind_indicator = (curr -> value )-> value .str .len ;
3894+ }
38603895 valueType = SQL_C_CHAR ;
38613896 paramValuePtr = (SQLPOINTER )((curr -> value )-> value .str .val );
38623897 } else {
@@ -3869,7 +3904,11 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
38693904
38703905 case SQL_BLOB :
38713906 if (curr -> param_type == DB2_PARAM_OUT || curr -> param_type == DB2_PARAM_INOUT ) {
3872- curr -> bind_indicator = (curr -> value )-> value .str .len ;
3907+ if (origlen != -1 ) {
3908+ curr -> bind_indicator = origlen ;
3909+ } else {
3910+ curr -> bind_indicator = (curr -> value )-> value .str .len ;
3911+ }
38733912#ifdef PASE /* i5/OS V6R1 incompatible change */
38743913 if (is_i5os_classic ){
38753914 valueType = SQL_C_BINARY ;
@@ -3907,7 +3946,11 @@ static int _php_db2_bind_data( stmt_handle *stmt_res, param_node *curr, zval **b
39073946 case SQL_VARBINARY :
39083947 case SQL_XML :
39093948 /* account for bin_mode settings as well */
3910- curr -> bind_indicator = (curr -> value )-> value .str .len ;
3949+ if (origlen != -1 ) {
3950+ curr -> bind_indicator = origlen ;
3951+ } else {
3952+ curr -> bind_indicator = (curr -> value )-> value .str .len ;
3953+ }
39113954#ifdef PASE /* i5/OS V6R1 incompatible change */
39123955 if (is_i5os_classic ){
39133956 valueType = SQL_C_BINARY ;
@@ -6589,7 +6632,8 @@ PHP_FUNCTION(db2_lob_read)
65896632 zval * stmt = NULL ;
65906633 stmt_handle * stmt_res ;
65916634 int rc , i = 0 ;
6592- SQLINTEGER out_length , length = BUFSIZ , colnum = 1 ;
6635+ SQLINTEGER out_length ;
6636+ long length = BUFSIZ , colnum = 1 ;
65936637 void * out_ptr = NULL ;
65946638
65956639 /* Parse out the parameters */
0 commit comments