2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
18 #include <ext/standard/php_smart_str.h>
21 #include "php_pq_misc.h"
22 #include "php_pq_object.h"
23 #include "php_pqexc.h"
24 #include "php_pqconn.h"
25 #include "php_pqres.h"
26 #include "php_pqstm.h"
28 zend_class_entry
*php_pqstm_class_entry
;
29 static zend_object_handlers php_pqstm_object_handlers
;
30 static HashTable php_pqstm_object_prophandlers
;
32 static void php_pqstm_deallocate(php_pqstm_object_t
*obj
, zend_bool async
, zend_bool silent TSRMLS_DC
)
34 if (obj
->intern
->allocated
) {
35 char *quoted_name
= PQescapeIdentifier(obj
->intern
->conn
->intern
->conn
, obj
->intern
->name
, strlen(obj
->intern
->name
));
40 smart_str_appends(&cmd
, "DEALLOCATE ");
41 smart_str_appends(&cmd
, quoted_name
);
45 if (PQsendQuery(obj
->intern
->conn
->intern
->conn
, cmd
.c
)) {
46 obj
->intern
->conn
->intern
->poller
= PQconsumeInput
;
47 php_pqconn_notify_listeners(obj
->intern
->conn TSRMLS_CC
);
49 throw_exce(EX_IO TSRMLS_CC
, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
54 if ((res
= php_pq_exec(obj
->intern
->conn
->intern
->conn
, cmd
.c
))) {
57 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
61 PQfreemem(quoted_name
);
65 obj
->intern
->allocated
= 0;
66 zend_hash_del(&obj
->intern
->conn
->intern
->statements
, obj
->intern
->name
, strlen(obj
->intern
->name
)+1);
70 static void php_pqstm_object_free(void *o TSRMLS_DC
)
72 php_pqstm_object_t
*obj
= o
;
74 fprintf(stderr
, "FREE stm(#%d) %p (conn(#%d): %p)\n", obj
->zv
.handle
, obj
, obj
->intern
->conn
->zv
.handle
, obj
->intern
->conn
);
77 if (obj
->intern
->conn
->intern
) {
78 php_pq_callback_dtor(&obj
->intern
->conn
->intern
->onevent
);
79 php_pqstm_deallocate(obj
, 0, 1 TSRMLS_CC
);
80 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
82 efree(obj
->intern
->name
);
83 efree(obj
->intern
->query
);
84 zend_hash_destroy(&obj
->intern
->bound
);
85 if (obj
->intern
->params
) {
86 php_pq_params_free(&obj
->intern
->params
);
91 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
95 zend_object_value
php_pqstm_create_object_ex(zend_class_entry
*ce
, php_pqstm_t
*intern
, php_pqstm_object_t
**ptr TSRMLS_DC
)
97 php_pqstm_object_t
*o
;
99 o
= ecalloc(1, sizeof(*o
));
100 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
101 object_properties_init((zend_object
*) o
, ce
);
102 o
->prophandler
= &php_pqstm_object_prophandlers
;
112 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqstm_object_free
, NULL TSRMLS_CC
);
113 o
->zv
.handlers
= &php_pqstm_object_handlers
;
118 static zend_object_value
php_pqstm_create_object(zend_class_entry
*class_type TSRMLS_DC
)
120 return php_pqstm_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
123 static void php_pqstm_object_read_name(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
125 php_pqstm_object_t
*obj
= o
;
127 RETVAL_STRING(obj
->intern
->name
, 1);
130 static void php_pqstm_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
132 php_pqstm_object_t
*obj
= o
;
134 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
137 static void php_pqstm_object_read_query(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
139 php_pqstm_object_t
*obj
= o
;
141 RETVAL_STRING(obj
->intern
->query
, 1);
144 static void php_pqstm_object_read_types(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
147 php_pqstm_object_t
*obj
= o
;
149 array_init_size(return_value
, obj
->intern
->params
->type
.count
);
150 for (i
= 0; i
< obj
->intern
->params
->type
.count
; i
++) {
151 add_next_index_long(return_value
, (long)obj
->intern
->params
->type
.oids
[i
]);
155 php_pqstm_t
*php_pqstm_init(php_pqconn_object_t
*conn
, const char *name
, const char *query
, php_pq_params_t
*params TSRMLS_DC
)
157 php_pqstm_t
*stm
= ecalloc(1, sizeof(*stm
));
159 php_pq_object_addref(conn TSRMLS_CC
);
161 stm
->name
= estrdup(name
);
162 stm
->params
= params
;
163 stm
->query
= estrdup(query
);
166 ZEND_INIT_SYMTABLE(&stm
->bound
);
168 zend_hash_add(&conn
->intern
->statements
, name
, strlen(name
)+1, &stm
, sizeof(stm
), NULL
);
173 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct
, 0, 0, 3)
174 ZEND_ARG_OBJ_INFO(0, connection
, pq
\\Connection
, 0)
175 ZEND_ARG_INFO(0, name
)
176 ZEND_ARG_INFO(0, query
)
177 ZEND_ARG_ARRAY_INFO(0, types
, 1)
178 ZEND_ARG_INFO(0, async
)
180 static PHP_METHOD(pqstm
, __construct
) {
181 zend_error_handling zeh
;
182 zval
*zconn
, *ztypes
= NULL
;
183 char *name_str
, *query_str
;
184 int name_len
, *query_len
;
188 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
189 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "Oss|a/!b", &zconn
, php_pqconn_class_entry
, &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
, &async
);
190 zend_restore_error_handling(&zeh TSRMLS_CC
);
193 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
194 php_pqconn_object_t
*conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
197 throw_exce(EX_BAD_METHODCALL TSRMLS_CC
, "pq\\Statement already initialized");
198 } else if (!conn_obj
->intern
) {
199 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
201 php_pq_params_t
*params
= php_pq_params_init(&conn_obj
->intern
->converters
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL
, NULL TSRMLS_CC
);
204 rv
= php_pqconn_prepare_async(zconn
, conn_obj
, name_str
, query_str
, params TSRMLS_CC
);
206 rv
= php_pqconn_prepare(zconn
, conn_obj
, name_str
, query_str
, params TSRMLS_CC
);
210 obj
->intern
= php_pqstm_init(conn_obj
, name_str
, query_str
, params TSRMLS_CC
);
215 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_bind
, 0, 0, 2)
216 ZEND_ARG_INFO(0, param_no
)
217 ZEND_ARG_INFO(1, param_ref
)
219 static PHP_METHOD(pqstm
, bind
) {
222 zend_error_handling zeh
;
225 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
226 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "lZ", ¶m_no
, ¶m_ref
);
227 zend_restore_error_handling(&zeh TSRMLS_CC
);
230 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
233 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
234 } else if (!obj
->intern
->allocated
) {
235 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement has been deallocated");
237 SEPARATE_ZVAL_TO_MAKE_IS_REF(param_ref
);
238 Z_ADDREF_PP(param_ref
);
239 zend_hash_index_update(&obj
->intern
->bound
, param_no
, (void *) param_ref
, sizeof(zval
*), NULL
);
240 zend_hash_sort(&obj
->intern
->bound
, zend_qsort
, php_pq_compare_index
, 0 TSRMLS_CC
);
245 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec
, 0, 0, 0)
246 ZEND_ARG_ARRAY_INFO(0, params
, 1)
248 static PHP_METHOD(pqstm
, exec
) {
249 zend_error_handling zeh
;
250 zval
*zparams
= NULL
;
253 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
254 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a/!", &zparams
);
255 zend_restore_error_handling(&zeh TSRMLS_CC
);
258 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
261 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
262 } else if (!obj
->intern
->allocated
) {
263 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement has been deallocated");
267 php_pq_params_set_params(obj
->intern
->params
, zparams
? Z_ARRVAL_P(zparams
) : &obj
->intern
->bound
);
268 res
= php_pq_exec_prepared(obj
->intern
->conn
->intern
->conn
, obj
->intern
->name
, obj
->intern
->params
->param
.count
, (const char *const*) obj
->intern
->params
->param
.strings
, NULL
, NULL
, 0);
269 php_pq_params_set_params(obj
->intern
->params
, NULL
);
272 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
273 } else if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
274 php_pq_object_to_zval_no_addref(PQresultInstanceData(res
, php_pqconn_event
), &return_value TSRMLS_CC
);
275 php_pqconn_notify_listeners(obj
->intern
->conn TSRMLS_CC
);
281 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec_async
, 0, 0, 0)
282 ZEND_ARG_ARRAY_INFO(0, params
, 1)
283 ZEND_ARG_INFO(0, callable
)
285 static PHP_METHOD(pqstm
, execAsync
) {
286 zend_error_handling zeh
;
287 zval
*zparams
= NULL
;
288 php_pq_callback_t resolver
= {{0}};
291 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
292 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a/!f", &zparams
, &resolver
.fci
, &resolver
.fcc
);
293 zend_restore_error_handling(&zeh TSRMLS_CC
);
296 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
299 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
300 } else if (!obj
->intern
->allocated
) {
301 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement has been deallocated");
305 php_pq_params_set_params(obj
->intern
->params
, zparams
? Z_ARRVAL_P(zparams
) : &obj
->intern
->bound
);
306 rc
= PQsendQueryPrepared(obj
->intern
->conn
->intern
->conn
, obj
->intern
->name
, obj
->intern
->params
->param
.count
, (const char *const*) obj
->intern
->params
->param
.strings
, NULL
, NULL
, 0);
307 php_pq_params_set_params(obj
->intern
->params
, NULL
);
310 throw_exce(EX_IO TSRMLS_CC
, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
311 #if HAVE_PQSETSINGLEROWMODE
312 } else if (obj
->intern
->conn
->intern
->unbuffered
&& !PQsetSingleRowMode(obj
->intern
->conn
->intern
->conn
)) {
313 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
316 php_pq_callback_recurse(&obj
->intern
->conn
->intern
->onevent
, &resolver TSRMLS_CC
);
317 obj
->intern
->conn
->intern
->poller
= PQconsumeInput
;
320 php_pqconn_notify_listeners(obj
->intern
->conn TSRMLS_CC
);
325 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc
, 0, 0, 0)
327 static PHP_METHOD(pqstm
, desc
) {
328 zend_error_handling zeh
;
331 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
332 rv
= zend_parse_parameters_none();
333 zend_restore_error_handling(&zeh TSRMLS_CC
);
336 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
339 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
340 } else if (!obj
->intern
->allocated
) {
341 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement has been deallocated");
343 PGresult
*res
= PQdescribePrepared(obj
->intern
->conn
->intern
->conn
, obj
->intern
->name
);
346 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to describe statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
348 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
351 array_init(return_value
);
352 for (p
= 0, params
= PQnparams(res
); p
< params
; ++p
) {
353 add_next_index_long(return_value
, PQparamtype(res
, p
));
356 php_pqres_clear(res
);
357 php_pqconn_notify_listeners(obj
->intern
->conn TSRMLS_CC
);
363 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc_async
, 0, 0, 1)
364 ZEND_ARG_INFO(0, callable
)
366 static PHP_METHOD(pqstm
, descAsync
) {
367 zend_error_handling zeh
;
368 php_pq_callback_t resolver
= {{0}};
371 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
372 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "f", &resolver
.fci
, &resolver
.fcc
);
373 zend_restore_error_handling(&zeh TSRMLS_CC
);
376 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
379 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
380 } else if (!obj
->intern
->allocated
) {
381 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement has been deallocated");
382 } else if (!PQsendDescribePrepared(obj
->intern
->conn
->intern
->conn
, obj
->intern
->name
)) {
383 throw_exce(EX_IO TSRMLS_CC
, "Failed to describe statement: %s", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
385 php_pq_callback_recurse(&obj
->intern
->conn
->intern
->onevent
, &resolver TSRMLS_CC
);
386 obj
->intern
->conn
->intern
->poller
= PQconsumeInput
;
387 php_pqconn_notify_listeners(obj
->intern
->conn TSRMLS_CC
);
392 static zend_always_inline
void php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PARAMETERS
, zend_bool async
)
394 zend_error_handling zeh
;
397 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
398 rv
= zend_parse_parameters_none();
399 zend_restore_error_handling(&zeh TSRMLS_CC
);
402 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
405 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
407 php_pqstm_deallocate(obj
, async
, 0 TSRMLS_CC
);
412 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_deallocate
, 0, 0, 0)
414 static PHP_METHOD(pqstm
, deallocate
)
416 php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU
, 0);
419 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_deallocate_async
, 0, 0, 0)
421 static PHP_METHOD(pqstm
, deallocateAsync
)
423 php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU
, 1);
426 static inline void php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAMETERS
, zend_bool async
)
428 zend_error_handling zeh
;
431 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
432 rv
= zend_parse_parameters_none();
433 zend_restore_error_handling(&zeh TSRMLS_CC
);
436 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
439 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Statement not initialized");
440 } else if (!obj
->intern
->allocated
) {
442 rv
= php_pqconn_prepare_async(NULL
, obj
->intern
->conn
, obj
->intern
->name
, obj
->intern
->query
, obj
->intern
->params TSRMLS_CC
);
444 rv
= php_pqconn_prepare(NULL
, obj
->intern
->conn
, obj
->intern
->name
, obj
->intern
->query
, obj
->intern
->params TSRMLS_CC
);
448 obj
->intern
->allocated
= 1;
450 zend_hash_add(&obj
->intern
->conn
->intern
->statements
,
451 obj
->intern
->name
, strlen(obj
->intern
->name
)+1, &obj
->intern
, sizeof(obj
->intern
), NULL
);
457 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_prepare
, 0, 0, 0)
459 static PHP_METHOD(pqstm
, prepare
)
461 php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU
, 0);
464 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_prepare_async
, 0, 0, 0)
466 static PHP_METHOD(pqstm
, prepareAsync
)
468 php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU
, 1);
471 static zend_function_entry php_pqstm_methods
[] = {
472 PHP_ME(pqstm
, __construct
, ai_pqstm_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
473 PHP_ME(pqstm
, bind
, ai_pqstm_bind
, ZEND_ACC_PUBLIC
)
474 PHP_ME(pqstm
, deallocate
, ai_pqstm_deallocate
, ZEND_ACC_PUBLIC
)
475 PHP_ME(pqstm
, deallocateAsync
, ai_pqstm_deallocate_async
, ZEND_ACC_PUBLIC
)
476 PHP_ME(pqstm
, desc
, ai_pqstm_desc
, ZEND_ACC_PUBLIC
)
477 PHP_ME(pqstm
, descAsync
, ai_pqstm_desc_async
, ZEND_ACC_PUBLIC
)
478 PHP_ME(pqstm
, exec
, ai_pqstm_exec
, ZEND_ACC_PUBLIC
)
479 PHP_ME(pqstm
, execAsync
, ai_pqstm_exec_async
, ZEND_ACC_PUBLIC
)
480 PHP_ME(pqstm
, prepare
, ai_pqstm_prepare
, ZEND_ACC_PUBLIC
)
481 PHP_ME(pqstm
, prepareAsync
, ai_pqstm_prepare_async
, ZEND_ACC_PUBLIC
)
485 PHP_MSHUTDOWN_FUNCTION(pqstm
)
487 zend_hash_destroy(&php_pqstm_object_prophandlers
);
491 PHP_MINIT_FUNCTION(pqstm
)
493 zend_class_entry ce
= {0};
494 php_pq_object_prophandler_t ph
= {0};
496 INIT_NS_CLASS_ENTRY(ce
, "pq", "Statement", php_pqstm_methods
);
497 php_pqstm_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
498 php_pqstm_class_entry
->create_object
= php_pqstm_create_object
;
500 memcpy(&php_pqstm_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
501 php_pqstm_object_handlers
.read_property
= php_pq_object_read_prop
;
502 php_pqstm_object_handlers
.write_property
= php_pq_object_write_prop
;
503 php_pqstm_object_handlers
.clone_obj
= NULL
;
504 php_pqstm_object_handlers
.get_property_ptr_ptr
= NULL
;
505 php_pqstm_object_handlers
.get_gc
= NULL
;
506 php_pqstm_object_handlers
.get_properties
= php_pq_object_properties
;
507 php_pqstm_object_handlers
.get_debug_info
= php_pq_object_debug_info
;
509 zend_hash_init(&php_pqstm_object_prophandlers
, 2, NULL
, NULL
, 1);
511 zend_declare_property_null(php_pqstm_class_entry
, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC
);
512 ph
.read
= php_pqstm_object_read_name
;
513 zend_hash_add(&php_pqstm_object_prophandlers
, "name", sizeof("name"), (void *) &ph
, sizeof(ph
), NULL
);
515 zend_declare_property_null(php_pqstm_class_entry
, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC
);
516 ph
.read
= php_pqstm_object_read_connection
;
517 zend_hash_add(&php_pqstm_object_prophandlers
, "connection", sizeof("connection"), (void *) &ph
, sizeof(ph
), NULL
);
519 zend_declare_property_null(php_pqstm_class_entry
, ZEND_STRL("query"), ZEND_ACC_PUBLIC TSRMLS_CC
);
520 ph
.read
= php_pqstm_object_read_query
;
521 zend_hash_add(&php_pqstm_object_prophandlers
, "query", sizeof("query"), (void *) &ph
, sizeof(ph
), NULL
);
523 zend_declare_property_null(php_pqstm_class_entry
, ZEND_STRL("types"), ZEND_ACC_PUBLIC TSRMLS_CC
);
524 ph
.read
= php_pqstm_object_read_types
;
525 zend_hash_add(&php_pqstm_object_prophandlers
, "types", sizeof("types"), (void *) &ph
, sizeof(ph
), NULL
);
535 * vim600: noet sw=4 ts=4 fdm=marker
536 * vim<600: noet sw=4 ts=4