@@ -135,6 +135,11 @@ static void free_cols(pdo_stmt_t *stmt, pdo_odbc_stmt *S)
135135 }
136136}
137137
138+ static void odbc_free_out_buffer (zval * el )
139+ {
140+ efree (Z_PTR_P (el ));
141+ }
142+
138143static int odbc_stmt_dtor (pdo_stmt_t * stmt )
139144{
140145 pdo_odbc_stmt * S = (pdo_odbc_stmt * )stmt -> driver_data ;
@@ -151,11 +156,41 @@ static int odbc_stmt_dtor(pdo_stmt_t *stmt)
151156 if (S -> convbuf ) {
152157 efree (S -> convbuf );
153158 }
159+ if (S -> out_buffers ) {
160+ zend_hash_destroy (S -> out_buffers );
161+ FREE_HASHTABLE (S -> out_buffers );
162+ }
154163 efree (S );
155164
156165 return 1 ;
157166}
158167
168+ static bool odbc_bind_param (pdo_stmt_t * stmt , struct pdo_bound_param_data * param )
169+ {
170+ pdo_odbc_stmt * S = (pdo_odbc_stmt * )stmt -> driver_data ;
171+ pdo_odbc_param * P = (pdo_odbc_param * )param -> driver_data ;
172+ RETCODE rc ;
173+
174+ if (!P ) {
175+ return true;
176+ }
177+
178+ rc = SQLBindParameter (S -> stmt , (SQLUSMALLINT ) param -> paramno + 1 ,
179+ P -> paramtype , P -> ctype , P -> sqltype , P -> precision , P -> scale ,
180+ P -> paramtype == SQL_PARAM_INPUT ?
181+ (SQLPOINTER )param :
182+ P -> outbuf ,
183+ P -> outbuf ? P -> outbuflen : 0 ,
184+ & P -> len
185+ );
186+
187+ if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO ) {
188+ return true;
189+ }
190+ pdo_odbc_stmt_error ("SQLBindParameter" );
191+ return false;
192+ }
193+
159194static int odbc_stmt_execute (pdo_stmt_t * stmt )
160195{
161196 RETCODE rc , rc1 ;
@@ -167,6 +202,24 @@ static int odbc_stmt_execute(pdo_stmt_t *stmt)
167202 SQLCloseCursor (S -> stmt );
168203 }
169204
205+ if (S -> params_dirty ) {
206+ rc = SQLFreeStmt (S -> stmt , SQL_RESET_PARAMS );
207+ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
208+ pdo_odbc_stmt_error ("SQLFreeStmt: SQL_RESET_PARAMS" );
209+ return 0 ;
210+ }
211+ if (stmt -> bound_params ) {
212+ struct pdo_bound_param_data * param ;
213+
214+ ZEND_HASH_FOREACH_PTR (stmt -> bound_params , param ) {
215+ if (!odbc_bind_param (stmt , param )) {
216+ return 0 ;
217+ }
218+ } ZEND_HASH_FOREACH_END ();
219+ }
220+ S -> params_dirty = false;
221+ }
222+
170223 rc = SQLExecute (S -> stmt );
171224
172225 while (rc == SQL_NEED_DATA ) {
@@ -310,6 +363,7 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
310363 if (P ) {
311364 efree (P );
312365 }
366+ S -> params_dirty = true;
313367 break ;
314368
315369 case PDO_PARAM_EVT_ALLOC :
@@ -384,6 +438,11 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
384438 }
385439 P -> outbuf = emalloc (P -> len + (P -> is_unicode ? 2 :1 ));
386440 P -> outbuflen = P -> len ;
441+ if (!S -> out_buffers ) {
442+ ALLOC_HASHTABLE (S -> out_buffers );
443+ zend_hash_init (S -> out_buffers , HT_MIN_SIZE , NULL , odbc_free_out_buffer , false);
444+ }
445+ zend_hash_next_index_insert_ptr (S -> out_buffers , P -> outbuf );
387446 }
388447 }
389448
@@ -392,20 +451,12 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
392451 return 0 ;
393452 }
394453
395- rc = SQLBindParameter (S -> stmt , (SQLUSMALLINT ) param -> paramno + 1 ,
396- P -> paramtype , ctype , sqltype , precision , scale ,
397- P -> paramtype == SQL_PARAM_INPUT ?
398- (SQLPOINTER )param :
399- P -> outbuf ,
400- P -> len ,
401- & P -> len
402- );
403-
404- if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO ) {
405- return 1 ;
406- }
407- pdo_odbc_stmt_error ("SQLBindParameter" );
408- return 0 ;
454+ P -> sqltype = sqltype ;
455+ P -> ctype = ctype ;
456+ P -> precision = precision ;
457+ P -> scale = scale ;
458+ S -> params_dirty = true;
459+ return 1 ;
409460 }
410461
411462 case PDO_PARAM_EVT_EXEC_PRE :
0 commit comments