@@ -133,6 +133,11 @@ static void free_cols(pdo_stmt_t *stmt, pdo_odbc_stmt *S)
133133 }
134134}
135135
136+ static void odbc_free_out_buffer (zval * el )
137+ {
138+ efree (Z_PTR_P (el ));
139+ }
140+
136141static int odbc_stmt_dtor (pdo_stmt_t * stmt )
137142{
138143 pdo_odbc_stmt * S = (pdo_odbc_stmt * )stmt -> driver_data ;
@@ -149,11 +154,41 @@ static int odbc_stmt_dtor(pdo_stmt_t *stmt)
149154 if (S -> convbuf ) {
150155 efree (S -> convbuf );
151156 }
157+ if (S -> out_buffers ) {
158+ zend_hash_destroy (S -> out_buffers );
159+ FREE_HASHTABLE (S -> out_buffers );
160+ }
152161 efree (S );
153162
154163 return 1 ;
155164}
156165
166+ static bool odbc_bind_param (pdo_stmt_t * stmt , struct pdo_bound_param_data * param )
167+ {
168+ pdo_odbc_stmt * S = (pdo_odbc_stmt * )stmt -> driver_data ;
169+ pdo_odbc_param * P = (pdo_odbc_param * )param -> driver_data ;
170+ RETCODE rc ;
171+
172+ if (!P ) {
173+ return true;
174+ }
175+
176+ rc = SQLBindParameter (S -> stmt , (SQLUSMALLINT ) param -> paramno + 1 ,
177+ P -> paramtype , P -> ctype , P -> sqltype , P -> precision , P -> scale ,
178+ P -> paramtype == SQL_PARAM_INPUT ?
179+ (SQLPOINTER )param :
180+ P -> outbuf ,
181+ P -> outbuf ? P -> outbuflen : 0 ,
182+ & P -> len
183+ );
184+
185+ if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO ) {
186+ return true;
187+ }
188+ pdo_odbc_stmt_error ("SQLBindParameter" );
189+ return false;
190+ }
191+
157192static int odbc_stmt_execute (pdo_stmt_t * stmt )
158193{
159194 RETCODE rc , rc1 ;
@@ -165,6 +200,24 @@ static int odbc_stmt_execute(pdo_stmt_t *stmt)
165200 SQLCloseCursor (S -> stmt );
166201 }
167202
203+ if (S -> params_dirty ) {
204+ rc = SQLFreeStmt (S -> stmt , SQL_RESET_PARAMS );
205+ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
206+ pdo_odbc_stmt_error ("SQLFreeStmt: SQL_RESET_PARAMS" );
207+ return 0 ;
208+ }
209+ if (stmt -> bound_params ) {
210+ struct pdo_bound_param_data * param ;
211+
212+ ZEND_HASH_FOREACH_PTR (stmt -> bound_params , param ) {
213+ if (!odbc_bind_param (stmt , param )) {
214+ return 0 ;
215+ }
216+ } ZEND_HASH_FOREACH_END ();
217+ }
218+ S -> params_dirty = false;
219+ }
220+
168221 rc = SQLExecute (S -> stmt );
169222
170223 while (rc == SQL_NEED_DATA ) {
@@ -308,6 +361,7 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
308361 if (P ) {
309362 efree (P );
310363 }
364+ S -> params_dirty = true;
311365 break ;
312366
313367 case PDO_PARAM_EVT_ALLOC :
@@ -382,6 +436,11 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
382436 }
383437 P -> outbuf = emalloc (P -> len + (P -> is_unicode ? 2 :1 ));
384438 P -> outbuflen = P -> len ;
439+ if (!S -> out_buffers ) {
440+ ALLOC_HASHTABLE (S -> out_buffers );
441+ zend_hash_init (S -> out_buffers , HT_MIN_SIZE , NULL , odbc_free_out_buffer , false);
442+ }
443+ zend_hash_next_index_insert_ptr (S -> out_buffers , P -> outbuf );
385444 }
386445 }
387446
@@ -390,20 +449,12 @@ static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *p
390449 return 0 ;
391450 }
392451
393- rc = SQLBindParameter (S -> stmt , (SQLUSMALLINT ) param -> paramno + 1 ,
394- P -> paramtype , ctype , sqltype , precision , scale ,
395- P -> paramtype == SQL_PARAM_INPUT ?
396- (SQLPOINTER )param :
397- P -> outbuf ,
398- P -> len ,
399- & P -> len
400- );
401-
402- if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO ) {
403- return 1 ;
404- }
405- pdo_odbc_stmt_error ("SQLBindParameter" );
406- return 0 ;
452+ P -> sqltype = sqltype ;
453+ P -> ctype = ctype ;
454+ P -> precision = precision ;
455+ P -> scale = scale ;
456+ S -> params_dirty = true;
457+ return 1 ;
407458 }
408459
409460 case PDO_PARAM_EVT_EXEC_PRE :
0 commit comments