fix leak; fix test
[m6w6/ext-pq] / src / php_pqstm.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: pq |
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 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <php.h>
18 #include <ext/standard/php_smart_str.h>
19
20 #include "php_pq.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"
27
28 zend_class_entry *php_pqstm_class_entry;
29 static zend_object_handlers php_pqstm_object_handlers;
30 static HashTable php_pqstm_object_prophandlers;
31
32 static void php_pqstm_deallocate(php_pqstm_object_t *obj, zend_bool async, zend_bool silent TSRMLS_DC)
33 {
34 if (obj->intern->allocated) {
35 char *quoted_name = PQescapeIdentifier(obj->intern->conn->intern->conn, obj->intern->name, strlen(obj->intern->name));
36
37 if (quoted_name) {
38 smart_str cmd = {0};
39
40 smart_str_appends(&cmd, "DEALLOCATE ");
41 smart_str_appends(&cmd, quoted_name);
42 smart_str_0(&cmd);
43
44 if (async) {
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);
48 } else if (!silent) {
49 throw_exce(EX_IO TSRMLS_CC, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
50 }
51 } else {
52 PGresult *res;
53
54 if ((res = PQexec(obj->intern->conn->intern->conn, cmd.c))) {
55 PHP_PQclear(res);
56 } else if (!silent) {
57 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
58 }
59 }
60
61 PQfreemem(quoted_name);
62 smart_str_free(&cmd);
63 }
64
65 obj->intern->allocated = 0;
66 }
67 }
68
69 static void php_pqstm_object_free(void *o TSRMLS_DC)
70 {
71 php_pqstm_object_t *obj = o;
72 #if DBG_GC
73 fprintf(stderr, "FREE stm(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn);
74 #endif
75 if (obj->intern) {
76 if (obj->intern->conn->intern) {
77 php_pq_callback_dtor(&obj->intern->conn->intern->onevent);
78 php_pqstm_deallocate(obj, 0, 1 TSRMLS_CC);
79 php_pq_object_delref(obj->intern->conn TSRMLS_CC);
80 }
81 efree(obj->intern->name);
82 efree(obj->intern->query);
83 zend_hash_destroy(&obj->intern->bound);
84 if (obj->intern->params) {
85 php_pq_params_free(&obj->intern->params);
86 }
87 efree(obj->intern);
88 obj->intern = NULL;
89 }
90 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
91 efree(obj);
92 }
93
94 zend_object_value php_pqstm_create_object_ex(zend_class_entry *ce, php_pqstm_t *intern, php_pqstm_object_t **ptr TSRMLS_DC)
95 {
96 php_pqstm_object_t *o;
97
98 o = ecalloc(1, sizeof(*o));
99 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
100 object_properties_init((zend_object *) o, ce);
101 o->prophandler = &php_pqstm_object_prophandlers;
102
103 if (ptr) {
104 *ptr = o;
105 }
106
107 if (intern) {
108 o->intern = intern;
109 }
110
111 o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqstm_object_free, NULL TSRMLS_CC);
112 o->zv.handlers = &php_pqstm_object_handlers;
113
114 return o->zv;
115 }
116
117 static zend_object_value php_pqstm_create_object(zend_class_entry *class_type TSRMLS_DC)
118 {
119 return php_pqstm_create_object_ex(class_type, NULL, NULL TSRMLS_CC);
120 }
121
122 static void php_pqstm_object_read_name(zval *object, void *o, zval *return_value TSRMLS_DC)
123 {
124 php_pqstm_object_t *obj = o;
125
126 RETVAL_STRING(obj->intern->name, 1);
127 }
128
129 static void php_pqstm_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC)
130 {
131 php_pqstm_object_t *obj = o;
132
133 php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC);
134 }
135
136 static void php_pqstm_object_read_query(zval *object, void *o, zval *return_value TSRMLS_DC)
137 {
138 php_pqstm_object_t *obj = o;
139
140 RETVAL_STRING(obj->intern->query, 1);
141 }
142
143 static void php_pqstm_object_read_types(zval *object, void *o, zval *return_value)
144 {
145 int i;
146 HashTable *ht;
147 php_pqstm_object_t *obj;
148
149 obj = (php_pqstm_object_t *)o;
150 ht = (HashTable *)emalloc(sizeof(HashTable));
151
152 zend_hash_init(ht, obj->intern->params->type.count, NULL, ZVAL_PTR_DTOR, 0);
153 Z_TYPE_P(return_value) = IS_ARRAY;
154 Z_ARRVAL_P(return_value) = ht;
155
156 for (i = 0; i < obj->intern->params->type.count; i++) {
157 add_next_index_long(return_value, (long)obj->intern->params->type.oids[i]);
158 }
159 }
160
161 php_pqstm_t *php_pqstm_init(php_pqconn_object_t *conn, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC)
162 {
163 php_pqstm_t *stm = ecalloc(1, sizeof(*stm));
164
165 php_pq_object_addref(conn TSRMLS_CC);
166 stm->conn = conn;
167 stm->name = estrdup(name);
168 stm->params = params;
169 stm->query = estrdup(query);
170 stm->allocated = 1;
171
172 ZEND_INIT_SYMTABLE(&stm->bound);
173
174 return stm;
175 }
176
177 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct, 0, 0, 3)
178 ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
179 ZEND_ARG_INFO(0, name)
180 ZEND_ARG_INFO(0, query)
181 ZEND_ARG_ARRAY_INFO(0, types, 1)
182 ZEND_ARG_INFO(0, async)
183 ZEND_END_ARG_INFO();
184 static PHP_METHOD(pqstm, __construct) {
185 zend_error_handling zeh;
186 zval *zconn, *ztypes = NULL;
187 char *name_str, *query_str;
188 int name_len, *query_len;
189 zend_bool async = 0;
190 STATUS rv;
191
192 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
193 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);
194 zend_restore_error_handling(&zeh TSRMLS_CC);
195
196 if (SUCCESS == rv) {
197 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
198 php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
199
200 if (obj->intern) {
201 throw_exce(EX_BAD_METHODCALL TSRMLS_CC, "pq\\Statement already initialized");
202 } else if (!conn_obj->intern) {
203 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
204 } else {
205 php_pq_params_t *params = php_pq_params_init(&conn_obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC);
206
207 if (async) {
208 rv = php_pqconn_prepare_async(zconn, conn_obj, name_str, query_str, params TSRMLS_CC);
209 } else {
210 rv = php_pqconn_prepare(zconn, conn_obj, name_str, query_str, params TSRMLS_CC);
211 }
212
213 if (SUCCESS == rv) {
214 obj->intern = php_pqstm_init(conn_obj, name_str, query_str, params TSRMLS_CC);
215 }
216 }
217 }
218 }
219 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_bind, 0, 0, 2)
220 ZEND_ARG_INFO(0, param_no)
221 ZEND_ARG_INFO(1, param_ref)
222 ZEND_END_ARG_INFO();
223 static PHP_METHOD(pqstm, bind) {
224 long param_no;
225 zval **param_ref;
226 zend_error_handling zeh;
227 STATUS rv;
228
229 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
230 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lZ", &param_no, &param_ref);
231 zend_restore_error_handling(&zeh TSRMLS_CC);
232
233 if (SUCCESS == rv) {
234 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
235
236 if (!obj->intern) {
237 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
238 } else if (!obj->intern->allocated) {
239 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated");
240 } else {
241 SEPARATE_ZVAL_TO_MAKE_IS_REF(param_ref);
242 Z_ADDREF_PP(param_ref);
243 zend_hash_index_update(&obj->intern->bound, param_no, (void *) param_ref, sizeof(zval *), NULL);
244 zend_hash_sort(&obj->intern->bound, zend_qsort, php_pq_compare_index, 0 TSRMLS_CC);
245 }
246 }
247 }
248
249 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec, 0, 0, 0)
250 ZEND_ARG_ARRAY_INFO(0, params, 1)
251 ZEND_END_ARG_INFO();
252 static PHP_METHOD(pqstm, exec) {
253 zend_error_handling zeh;
254 zval *zparams = NULL;
255 STATUS rv;
256
257 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
258 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &zparams);
259 zend_restore_error_handling(&zeh TSRMLS_CC);
260
261 if (SUCCESS == rv) {
262 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
263
264 if (!obj->intern) {
265 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
266 } else if (!obj->intern->allocated) {
267 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated");
268 } else {
269 PGresult *res;
270
271 php_pq_params_set_params(obj->intern->params, zparams ? Z_ARRVAL_P(zparams) : &obj->intern->bound);
272 res = PQexecPrepared(obj->intern->conn->intern->conn, obj->intern->name, obj->intern->params->param.count, (const char *const*) obj->intern->params->param.strings, NULL, NULL, 0);
273 php_pq_params_set_params(obj->intern->params, NULL);
274
275 if (!res) {
276 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
277 } else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
278 php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
279 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
280 }
281 }
282 }
283 }
284
285 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec_async, 0, 0, 0)
286 ZEND_ARG_ARRAY_INFO(0, params, 1)
287 ZEND_ARG_INFO(0, callable)
288 ZEND_END_ARG_INFO();
289 static PHP_METHOD(pqstm, execAsync) {
290 zend_error_handling zeh;
291 zval *zparams = NULL;
292 php_pq_callback_t resolver = {{0}};
293 STATUS rv;
294
295 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
296 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!f", &zparams, &resolver.fci, &resolver.fcc);
297 zend_restore_error_handling(&zeh TSRMLS_CC);
298
299 if (SUCCESS == rv) {
300 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
301
302 if (!obj->intern) {
303 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
304 } else if (!obj->intern->allocated) {
305 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated");
306 } else {
307 int rc;
308
309 php_pq_params_set_params(obj->intern->params, zparams ? Z_ARRVAL_P(zparams) : &obj->intern->bound);
310 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);
311 php_pq_params_set_params(obj->intern->params, NULL);
312
313 if (!rc) {
314 throw_exce(EX_IO TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
315 #if HAVE_PQSETSINGLEROWMODE
316 } else if (obj->intern->conn->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn->intern->conn)) {
317 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
318 #endif
319 } else {
320 php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver TSRMLS_CC);
321 obj->intern->conn->intern->poller = PQconsumeInput;
322 }
323
324 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
325 }
326 }
327 }
328
329 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc, 0, 0, 0)
330 ZEND_END_ARG_INFO();
331 static PHP_METHOD(pqstm, desc) {
332 zend_error_handling zeh;
333 STATUS rv;
334
335 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
336 rv = zend_parse_parameters_none();
337 zend_restore_error_handling(&zeh TSRMLS_CC);
338
339 if (SUCCESS == rv) {
340 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
341
342 if (!obj->intern) {
343 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
344 } else if (!obj->intern->allocated) {
345 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated");
346 } else {
347 PGresult *res = PQdescribePrepared(obj->intern->conn->intern->conn, obj->intern->name);
348
349 if (!res) {
350 throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to describe statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
351 } else {
352 if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
353 int p, params;
354
355 array_init(return_value);
356 for (p = 0, params = PQnparams(res); p < params; ++p) {
357 add_next_index_long(return_value, PQparamtype(res, p));
358 }
359 }
360 PHP_PQclear(res);
361 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
362 }
363 }
364 }
365 }
366
367 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc_async, 0, 0, 1)
368 ZEND_ARG_INFO(0, callable)
369 ZEND_END_ARG_INFO();
370 static PHP_METHOD(pqstm, descAsync) {
371 zend_error_handling zeh;
372 php_pq_callback_t resolver = {{0}};
373 STATUS rv;
374
375 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
376 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", &resolver.fci, &resolver.fcc);
377 zend_restore_error_handling(&zeh TSRMLS_CC);
378
379 if (SUCCESS == rv) {
380 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
381
382 if (!obj->intern) {
383 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
384 } else if (!obj->intern->allocated) {
385 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated");
386 } else if (!PQsendDescribePrepared(obj->intern->conn->intern->conn, obj->intern->name)) {
387 throw_exce(EX_IO TSRMLS_CC, "Failed to describe statement: %s", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
388 } else {
389 php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver TSRMLS_CC);
390 obj->intern->conn->intern->poller = PQconsumeInput;
391 php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
392 }
393 }
394 }
395
396 static zend_always_inline void php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PARAMETERS, zend_bool async)
397 {
398 zend_error_handling zeh;
399 STATUS rv;
400
401 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
402 rv = zend_parse_parameters_none();
403 zend_restore_error_handling(&zeh TSRMLS_CC);
404
405 if (rv == SUCCESS) {
406 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
407
408 if (!obj->intern) {
409 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
410 } else {
411 php_pqstm_deallocate(obj, async, 0 TSRMLS_CC);
412 }
413 }
414 }
415
416 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_deallocate, 0, 0, 0)
417 ZEND_END_ARG_INFO();
418 static PHP_METHOD(pqstm, deallocate)
419 {
420 php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
421 }
422
423 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_deallocate_async, 0, 0, 0)
424 ZEND_END_ARG_INFO();
425 static PHP_METHOD(pqstm, deallocateAsync)
426 {
427 php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
428 }
429
430 static zend_always_inline void php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAMETERS, zend_bool async)
431 {
432 zend_error_handling zeh;
433 STATUS rv;
434
435 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
436 rv = zend_parse_parameters_none();
437 zend_restore_error_handling(&zeh TSRMLS_CC);
438
439 if (rv == SUCCESS) {
440 php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
441
442 if (!obj->intern) {
443 throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
444 } else if (!obj->intern->allocated) {
445 if (async) {
446 rv = php_pqconn_prepare_async(NULL, obj->intern->conn, obj->intern->name, obj->intern->query, obj->intern->params TSRMLS_CC);
447 } else {
448 rv = php_pqconn_prepare(NULL, obj->intern->conn, obj->intern->name, obj->intern->query, obj->intern->params TSRMLS_CC);
449 }
450
451 if (SUCCESS == rv) {
452 obj->intern->allocated = 1;
453 }
454 }
455 }
456 }
457
458 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_prepare, 0, 0, 0)
459 ZEND_END_ARG_INFO();
460 static PHP_METHOD(pqstm, prepare)
461 {
462 php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
463 }
464
465 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_prepare_async, 0, 0, 0)
466 ZEND_END_ARG_INFO();
467 static PHP_METHOD(pqstm, prepareAsync)
468 {
469 php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
470 }
471
472 static zend_function_entry php_pqstm_methods[] = {
473 PHP_ME(pqstm, __construct, ai_pqstm_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
474 PHP_ME(pqstm, bind, ai_pqstm_bind, ZEND_ACC_PUBLIC)
475 PHP_ME(pqstm, deallocate, ai_pqstm_deallocate, ZEND_ACC_PUBLIC)
476 PHP_ME(pqstm, deallocateAsync, ai_pqstm_deallocate_async, ZEND_ACC_PUBLIC)
477 PHP_ME(pqstm, desc, ai_pqstm_desc, ZEND_ACC_PUBLIC)
478 PHP_ME(pqstm, descAsync, ai_pqstm_desc_async, ZEND_ACC_PUBLIC)
479 PHP_ME(pqstm, exec, ai_pqstm_exec, ZEND_ACC_PUBLIC)
480 PHP_ME(pqstm, execAsync, ai_pqstm_exec_async, ZEND_ACC_PUBLIC)
481 PHP_ME(pqstm, prepare, ai_pqstm_prepare, ZEND_ACC_PUBLIC)
482 PHP_ME(pqstm, prepareAsync, ai_pqstm_prepare_async, ZEND_ACC_PUBLIC)
483 {0}
484 };
485
486 PHP_MSHUTDOWN_FUNCTION(pqstm)
487 {
488 zend_hash_destroy(&php_pqstm_object_prophandlers);
489 return SUCCESS;
490 }
491
492 PHP_MINIT_FUNCTION(pqstm)
493 {
494 zend_class_entry ce = {0};
495 php_pq_object_prophandler_t ph = {0};
496
497 INIT_NS_CLASS_ENTRY(ce, "pq", "Statement", php_pqstm_methods);
498 php_pqstm_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
499 php_pqstm_class_entry->create_object = php_pqstm_create_object;
500
501 memcpy(&php_pqstm_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
502 php_pqstm_object_handlers.read_property = php_pq_object_read_prop;
503 php_pqstm_object_handlers.write_property = php_pq_object_write_prop;
504 php_pqstm_object_handlers.clone_obj = NULL;
505 php_pqstm_object_handlers.get_property_ptr_ptr = NULL;
506 php_pqstm_object_handlers.get_gc = NULL;
507 php_pqstm_object_handlers.get_properties = php_pq_object_properties;
508 php_pqstm_object_handlers.get_debug_info = php_pq_object_debug_info;
509
510 zend_hash_init(&php_pqstm_object_prophandlers, 2, NULL, NULL, 1);
511
512 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC);
513 ph.read = php_pqstm_object_read_name;
514 zend_hash_add(&php_pqstm_object_prophandlers, "name", sizeof("name"), (void *) &ph, sizeof(ph), NULL);
515
516 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC);
517 ph.read = php_pqstm_object_read_connection;
518 zend_hash_add(&php_pqstm_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL);
519
520 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("query"), ZEND_ACC_PUBLIC TSRMLS_CC);
521 ph.read = php_pqstm_object_read_query;
522 zend_hash_add(&php_pqstm_object_prophandlers, "query", sizeof("query"), (void *) &ph, sizeof(ph), NULL);
523
524 zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("types"), ZEND_ACC_PUBLIC TSRMLS_CC);
525 ph.read = php_pqstm_object_read_types;
526 zend_hash_add(&php_pqstm_object_prophandlers, "types", sizeof("types"), (void *) &ph, sizeof(ph), NULL);
527
528 return SUCCESS;
529 }
530
531 /*
532 * Local variables:
533 * tab-width: 4
534 * c-basic-offset: 4
535 * End:
536 * vim600: noet sw=4 ts=4 fdm=marker
537 * vim<600: noet sw=4 ts=4
538 */