@@ -46,11 +46,16 @@ typedef struct {
4646 unsigned short el_type , el_size ;
4747} ibase_array ;
4848
49+ typedef struct {
50+ ibase_db_link * link ;
51+ isc_stmt_handle stmt ;
52+ } ibase_statement ;
53+
4954typedef struct {
5055 ibase_db_link * link ;
5156 ibase_trans * trans ;
52- struct _ib_query * query ;
5357 isc_stmt_handle stmt ;
58+ zend_resource * stmt_res ;
5459 unsigned short type ;
5560 unsigned char has_more_rows , statement_type ;
5661 XSQLDA * out_sqlda ;
@@ -60,9 +65,9 @@ typedef struct {
6065typedef struct _ib_query {
6166 ibase_db_link * link ;
6267 ibase_trans * trans ;
63- ibase_result * result ;
6468 zend_resource * result_res ;
6569 isc_stmt_handle stmt ;
70+ zend_resource * stmt_res ;
6671 XSQLDA * in_sqlda , * out_sqlda ;
6772 ibase_array * in_array , * out_array ;
6873 unsigned short in_array_cnt , out_array_cnt ;
@@ -94,7 +99,7 @@ typedef struct {
9499 short sqlind ;
95100} BIND_BUF ;
96101
97- static int le_result , le_query ;
102+ static int le_statement , le_result , le_query ;
98103
99104#define LE_RESULT "Firebird/InterBase result"
100105#define LE_QUERY "Firebird/InterBase query"
@@ -119,20 +124,25 @@ static void _php_ibase_free_xsqlda(XSQLDA *sqlda) /* {{{ */
119124}
120125/* }}} */
121126
122- static void _php_ibase_free_stmt_handle ( ibase_db_link * link , isc_stmt_handle stmt ) /* {{{ */
127+ static void _php_ibase_free_statement ( zend_resource * rsrc ) /* {{{ */
123128{
124- static char info [] = { isc_info_base_level , isc_info_end };
125-
126- if (stmt ) {
127- char res_buf [8 ];
128- IBDEBUG ("Dropping statement handle (free_stmt_handle)..." );
129- /* Only free statement if db-connection is still open */
130- if (SUCCESS == isc_database_info (IB_STATUS , & link -> handle ,
131- sizeof (info ), info , sizeof (res_buf ), res_buf )) {
132- if (isc_dsql_free_statement (IB_STATUS , & stmt , DSQL_drop )) {
133- _php_ibase_error ();
129+ ibase_statement * ib_stmt = (ibase_statement * )rsrc -> ptr ;
130+
131+ IBDEBUG ("Freeing statement by dtor..." );
132+ if (ib_stmt ) {
133+ if (ib_stmt -> stmt ) {
134+ static char info [] = { isc_info_base_level , isc_info_end };
135+ char res_buf [8 ];
136+ IBDEBUG ("Dropping statement handle (free_stmt_handle)..." );
137+ /* Only free statement if db-connection is still open */
138+ if (SUCCESS == isc_database_info (IB_STATUS , & ib_stmt -> link -> handle ,
139+ sizeof (info ), info , sizeof (res_buf ), res_buf )) {
140+ if (isc_dsql_free_statement (IB_STATUS , & ib_stmt -> stmt , DSQL_drop )) {
141+ _php_ibase_error ();
142+ }
134143 }
135144 }
145+ efree (ib_stmt );
136146 }
137147}
138148/* }}} */
@@ -144,14 +154,8 @@ static void _php_ibase_free_result(zend_resource *rsrc) /* {{{ */
144154 IBDEBUG ("Freeing result by dtor..." );
145155 if (ib_result ) {
146156 _php_ibase_free_xsqlda (ib_result -> out_sqlda );
147- if (ib_result -> query != NULL ) {
148- IBDEBUG ("query still valid; don't drop statement handle" );
149- if (ib_result -> query -> result == ib_result ) {
150- /* If we are the last execution result on the query */
151- ib_result -> query -> result = NULL ; /* Indicate to query, that result is released */
152- }
153- } else {
154- _php_ibase_free_stmt_handle (ib_result -> link , ib_result -> stmt );
157+ if (ib_result -> stmt_res != NULL ) {
158+ zend_list_delete (ib_result -> stmt_res );
155159 }
156160 efree (ib_result );
157161 }
@@ -168,13 +172,8 @@ static void _php_ibase_free_query(ibase_query *ib_query) /* {{{ */
168172 if (ib_query -> out_sqlda ) {
169173 efree (ib_query -> out_sqlda );
170174 }
171- if (ib_query -> result != NULL ) {
172- IBDEBUG ("result still valid; don't drop statement handle" );
173- if (ib_query -> result -> query == ib_query ) {
174- ib_query -> result -> query = NULL ; /* Indicate to result, that query is released */
175- }
176- } else {
177- _php_ibase_free_stmt_handle (ib_query -> link , ib_query -> stmt );
175+ if (ib_query -> stmt_res != NULL ) {
176+ zend_list_delete (ib_query -> stmt_res );
178177 }
179178 if (ib_query -> in_array ) {
180179 efree (ib_query -> in_array );
@@ -202,6 +201,8 @@ static void php_ibase_free_query_rsrc(zend_resource *rsrc) /* {{{ */
202201
203202void php_ibase_query_minit (INIT_FUNC_ARGS ) /* {{{ */
204203{
204+ le_statement = zend_register_list_destructors_ex (_php_ibase_free_statement , NULL ,
205+ "interbase statement" , module_number );
205206 le_result = zend_register_list_destructors_ex (_php_ibase_free_result , NULL ,
206207 "interbase result" , module_number );
207208 le_query = zend_register_list_destructors_ex (php_ibase_free_query_rsrc , NULL ,
@@ -341,6 +342,7 @@ static int _php_ibase_alloc_query(ibase_query *ib_query, ibase_db_link *link, /*
341342 ib_query -> result_res = NULL ;
342343 ib_query -> result = NULL ;
343344 ib_query -> stmt = 0 ;
345+ ib_query -> stmt_res = NULL ;
344346 ib_query -> in_array = NULL ;
345347 ib_query -> out_array = NULL ;
346348 ib_query -> dialect = dialect ;
@@ -353,6 +355,12 @@ static int _php_ibase_alloc_query(ibase_query *ib_query, ibase_db_link *link, /*
353355 _php_ibase_error ();
354356 goto _php_ibase_alloc_query_error ;
355357 }
358+ { /* allocate zend resource for statement*/
359+ ibase_statement * ib_stmt = emalloc (sizeof (ibase_statement ));
360+ ib_stmt -> link = link ;
361+ ib_stmt -> stmt = ib_query -> stmt ;
362+ ib_query -> stmt_res = zend_register_resource (ib_stmt , le_statement );
363+ }
356364
357365 ib_query -> out_sqlda = (XSQLDA * ) emalloc (XSQLDA_LENGTH (1 ));
358366 ib_query -> out_sqlda -> sqln = 1 ;
@@ -1002,8 +1010,9 @@ static int _php_ibase_exec(INTERNAL_FUNCTION_PARAMETERS, ibase_result **ib_resul
10021010 res -> link = ib_query -> link ;
10031011 res -> trans = ib_query -> trans ;
10041012 res -> stmt = ib_query -> stmt ;
1005- /* ib_result and ib_query point at each other to handle release of statement handle properly */
1006- res -> query = ib_query ;
1013+ res -> stmt_res = ib_query -> stmt_res ;
1014+ ++ GC_REFCOUNT (res -> stmt_res ); // Addref the resource for the result
1015+
10071016 ib_query -> result = res ;
10081017 res -> statement_type = ib_query -> statement_type ;
10091018 res -> has_more_rows = 1 ;
0 commit comments