prepare v2.2.3
[m6w6/ext-pq] / src / php_pqres.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
19 #include <ext/spl/spl_iterators.h>
20 #if PHP_PQ_HAVE_PHP_JSON_H
21 #include <php_json.h> /* we've added the include directory to INCLUDES */
22 #endif
23
24 #include <libpq-events.h>
25
26 #include "php_pq.h"
27 #include "php_pq_misc.h"
28 #include "php_pq_object.h"
29 #include "php_pqexc.h"
30 #include "php_pqres.h"
31 #undef PHP_PQ_TYPE
32 #include "php_pq_type.h"
33
34 zend_class_entry *php_pqres_class_entry;
35 static zend_object_handlers php_pqres_object_handlers;
36 static HashTable php_pqres_object_prophandlers;
37 static zend_object_iterator_funcs php_pqres_iterator_funcs;
38
39 static inline zend_object_iterator *php_pqres_iterator_init_ex(zend_class_entry *ce, zval *object, int by_ref)
40 {
41 php_pqres_iterator_t *iter;
42 zval tmp, *zfetch_type;
43
44 iter = ecalloc(1, sizeof(*iter));
45 iter->zi.funcs = &php_pqres_iterator_funcs;
46 ZVAL_COPY_VALUE(&iter->zi.data, object);
47
48 zfetch_type = php_pq_read_property(object, "fetchType", &tmp);
49 iter->fetch_type = zval_get_long(zfetch_type);
50 #if DBG_GC
51 fprintf(stderr, "INIT iter(#%d) %p res(#%d) %p\n", iter->zi.std.handle, iter, Z_OBJ_HANDLE_P(object), PHP_PQ_OBJ(object, NULL));
52 #endif
53 return (zend_object_iterator *) iter;
54 }
55
56 static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval *object, int by_ref)
57 {
58 zend_object_iterator *iter = php_pqres_iterator_init_ex(ce, object, by_ref);
59
60 zend_iterator_init(iter);
61 Z_ADDREF_P(object);
62
63 return iter;
64 }
65 static void php_pqres_internal_iterator_init(zval *zobj)
66 {
67 php_pqres_object_t *obj = PHP_PQ_OBJ(zobj, NULL);
68
69 obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init_ex(Z_OBJCE_P(zobj), zobj, 0);
70 obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter);
71
72 }
73
74 static inline void php_pqres_iterator_dtor_ex(zend_object_iterator *i)
75 {
76 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
77
78 #if DBG_GC
79 fprintf(stderr, "FREE iter(#%d) rc=%d %p\n", iter->zi.std.handle, GC_REFCOUNT(&iter->zi.std), iter);
80 #endif
81 if (!Z_ISUNDEF(iter->current_val)) {
82 zval_ptr_dtor(&iter->current_val);
83 ZVAL_UNDEF(&iter->current_val);
84 }
85 }
86
87 static void php_pqres_iterator_dtor(zend_object_iterator *i)
88 {
89 php_pqres_iterator_dtor_ex(i);
90 zval_ptr_dtor(&i->data);
91 }
92
93 static void php_pqres_internal_iterator_dtor(php_pqres_object_t *obj)
94 {
95 if (obj->intern && obj->intern->iter) {
96 php_pqres_iterator_dtor_ex((zend_object_iterator *) obj->intern->iter);
97 efree(obj->intern->iter);
98 obj->intern->iter = NULL;
99 }
100 }
101
102 static ZEND_RESULT_CODE php_pqres_iterator_valid(zend_object_iterator *i)
103 {
104 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
105 php_pqres_object_t *obj = PHP_PQ_OBJ(&i->data, NULL);
106
107 switch (PQresultStatus(obj->intern->res)) {
108 case PGRES_TUPLES_OK:
109 #ifdef HAVE_PGRES_SINGLE_TUPLE
110 case PGRES_SINGLE_TUPLE:
111 #endif
112 if (PQntuples(obj->intern->res) <= iter->index) {
113 return FAILURE;
114 }
115 break;
116 default:
117 return FAILURE;
118 }
119
120 return SUCCESS;
121 }
122
123 #define PHP_PQRES_JSON_OPTIONS(res) \
124 (php_pqres_fetch_type(res) != PHP_PQRES_FETCH_OBJECT ? PHP_JSON_OBJECT_AS_ARRAY:0)
125
126 zval *php_pqres_typed_zval(php_pqres_t *res, Oid typ, zval *zv)
127 {
128 zval *zconv;
129 HashTable *ht;
130 zend_string *str;
131
132 if ((zconv = zend_hash_index_find(&res->converters, typ))) {
133 zval ztype, rv;
134
135 ZVAL_NULL(&rv);
136 ZVAL_LONG(&ztype, typ);
137 php_pq_call_method(zconv, "convertfromstring", 2, &rv, zv, &ztype);
138
139 zval_ptr_dtor(zv);
140 ZVAL_ZVAL(zv, &rv, 0, 0);
141
142 return zv;
143 }
144
145 str = zval_get_string(zv);
146 zval_ptr_dtor(zv);
147
148 switch (typ) {
149 case PHP_PQ_OID_BOOL:
150 if (!(res->auto_convert & PHP_PQRES_CONV_BOOL)) {
151 goto noconversion;
152 }
153 ZVAL_BOOL(zv, *str->val == 't');
154 break;
155
156 case PHP_PQ_OID_INT8:
157 case PHP_PQ_OID_TID:
158 case PHP_PQ_OID_INT4:
159 case PHP_PQ_OID_INT2:
160 case PHP_PQ_OID_XID:
161 case PHP_PQ_OID_OID:
162 if (!(res->auto_convert & PHP_PQRES_CONV_INT)) {
163 goto noconversion;
164 }
165 {
166 zend_long lval;
167 double dval;
168
169 switch (is_numeric_str_function(str, &lval, &dval)) {
170 case IS_LONG:
171 ZVAL_LONG(zv, lval);
172 break;
173 case IS_DOUBLE:
174 ZVAL_DOUBLE(zv, dval);
175 break;
176 default:
177 goto noconversion;
178 }
179 }
180 break;
181
182 case PHP_PQ_OID_FLOAT4:
183 case PHP_PQ_OID_FLOAT8:
184 if (!(res->auto_convert & PHP_PQRES_CONV_FLOAT)) {
185 goto noconversion;
186 }
187 ZVAL_DOUBLE(zv, zend_strtod(str->val, NULL));
188 break;
189
190 case PHP_PQ_OID_DATE:
191 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
192 goto noconversion;
193 }
194 php_pqdt_from_string(zv, NULL, str->val, str->len, "Y-m-d", NULL);
195 break;
196 #ifdef PHP_PQ_OID_ABSTIME
197 case PHP_PQ_OID_ABSTIME:
198 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
199 goto noconversion;
200 }
201 php_pqdt_from_string(zv, NULL, str->val, str->len, "Y-m-d H:i:s", NULL);
202 break;
203 #endif
204 case PHP_PQ_OID_TIMESTAMP:
205 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
206 goto noconversion;
207 }
208 php_pqdt_from_string(zv, NULL, str->val, str->len, "Y-m-d H:i:s.u", NULL);
209 break;
210
211 case PHP_PQ_OID_TIMESTAMPTZ:
212 if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) {
213 goto noconversion;
214 }
215 php_pqdt_from_string(zv, NULL, str->val, str->len, "Y-m-d H:i:s.uO", NULL);
216 break;
217
218 #if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
219 # ifdef PHP_PQ_OID_JSONB
220 case PHP_PQ_OID_JSONB:
221 # endif
222 case PHP_PQ_OID_JSON:
223 if (!(res->auto_convert & PHP_PQRES_CONV_JSON)) {
224 goto noconversion;
225 }
226 php_json_decode_ex(zv, str->val, str->len, PHP_PQRES_JSON_OPTIONS(res), 512 /* PHP_JSON_DEFAULT_DEPTH */);
227 break;
228 #endif
229
230 default:
231 if (!(res->auto_convert & PHP_PQRES_CONV_ARRAY)) {
232 goto noconversion;
233 }
234 if (PHP_PQ_TYPE_IS_ARRAY(typ) && (ht = php_pq_parse_array(res, str->val, str->len, PHP_PQ_TYPE_OF_ARRAY(typ)))) {
235 ZVAL_ARR(zv, ht);
236 } else {
237 goto noconversion;
238 }
239 break;
240 }
241
242 zend_string_release(str);
243 return zv;
244
245 noconversion:
246 ZVAL_STR(zv, str);
247 return zv;
248 }
249
250 static inline zval *php_pqres_get_col(php_pqres_t *r, unsigned row, unsigned col, zval *zv)
251 {
252 if (PQgetisnull(r->res, row, col)) {
253 ZVAL_NULL(zv);
254 } else {
255 ZVAL_STRINGL(zv, PQgetvalue(r->res, row, col), PQgetlength(r->res, row, col));
256 zv = php_pqres_typed_zval(r, PQftype(r->res, col), zv);
257 }
258
259 return zv;
260 }
261
262 static inline void php_pqres_add_col_to_zval(php_pqres_t *r, unsigned row, unsigned col, php_pqres_fetch_t fetch_type, zval *data)
263 {
264 if (PQgetisnull(r->res, row, col)) {
265 switch (fetch_type) {
266 case PHP_PQRES_FETCH_OBJECT:
267 add_property_null(data, PQfname(r->res, col));
268 break;
269
270 case PHP_PQRES_FETCH_ASSOC:
271 add_assoc_null(data, PQfname(r->res, col));
272 break;
273
274 case PHP_PQRES_FETCH_ARRAY:
275 add_index_null(data, col);
276 break;
277 }
278 } else {
279 zval zv;
280
281 ZVAL_STRINGL(&zv, PQgetvalue(r->res, row, col), PQgetlength(r->res, row, col));
282 php_pqres_typed_zval(r, PQftype(r->res, col), &zv);
283
284 switch (fetch_type) {
285 case PHP_PQRES_FETCH_OBJECT:
286 add_property_zval(data, PQfname(r->res, col), &zv);
287 zval_ptr_dtor(&zv);
288 break;
289
290 case PHP_PQRES_FETCH_ASSOC:
291 add_assoc_zval(data, PQfname(r->res, col), &zv);
292 break;
293
294 case PHP_PQRES_FETCH_ARRAY:
295 add_index_zval(data, col, &zv);
296 break;
297 }
298 }
299 }
300
301 zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type, zval *data)
302 {
303 int c, cols = PQnfields(res);
304 php_pqres_object_t *res_obj = PQresultInstanceData(res, php_pqconn_event);
305
306 if (Z_TYPE_P(data) != IS_OBJECT && Z_TYPE_P(data) != IS_ARRAY) {
307 if (PHP_PQRES_FETCH_OBJECT == fetch_type) {
308 object_init(data);
309 } else {
310 array_init_size(data, cols);
311 }
312 }
313
314 if (PQntuples(res) > row) {
315 for (c = 0; c < cols; ++c) {
316 php_pqres_add_col_to_zval(res_obj->intern, row, c, fetch_type, data);
317 }
318 }
319
320 return data;
321 }
322
323 static zval *php_pqres_iterator_current(zend_object_iterator *i)
324 {
325 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
326 php_pqres_object_t *obj = PHP_PQ_OBJ(&i->data, NULL);
327
328 if (Z_ISUNDEF(iter->current_val)) {
329 php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type, &iter->current_val);
330 }
331 return &iter->current_val;
332 }
333
334 static void php_pqres_iterator_key(zend_object_iterator *i, zval *key)
335 {
336 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
337
338 ZVAL_LONG(key, iter->index);
339 }
340
341 static void php_pqres_iterator_invalidate(zend_object_iterator *i)
342 {
343 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
344
345 if (!Z_ISUNDEF(iter->current_val)) {
346 zval_ptr_dtor(&iter->current_val);
347 ZVAL_UNDEF(&iter->current_val);
348 }
349 }
350
351 static void php_pqres_iterator_next(zend_object_iterator *i)
352 {
353 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
354
355 php_pqres_iterator_invalidate(i);
356 ++iter->index;
357 }
358
359 static void php_pqres_iterator_rewind(zend_object_iterator *i)
360 {
361 php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i;
362
363 php_pqres_iterator_invalidate(i);
364 iter->index = 0;
365 }
366
367 static zend_object_iterator_funcs php_pqres_iterator_funcs = {
368 php_pqres_iterator_dtor,
369 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
370 php_pqres_iterator_valid,
371 /* fetch the item data for the current element */
372 php_pqres_iterator_current,
373 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
374 php_pqres_iterator_key,
375 /* step forwards to next element */
376 php_pqres_iterator_next,
377 /* rewind to start of data (optional, may be NULL) */
378 php_pqres_iterator_rewind,
379 /* invalidate current value/key (optional, may be NULL) */
380 php_pqres_iterator_invalidate
381 #if PHP_VERSION_ID >= 80000
382 , NULL
383 #endif
384 };
385
386 static inline ZEND_RESULT_CODE php_pqres_count_elements_ex(zend_object *object, long *count)
387 {
388 php_pqres_object_t *obj = PHP_PQ_OBJ(NULL, object);
389
390 if (!obj->intern) {
391 return FAILURE;
392 } else {
393 *count = (long) PQntuples(obj->intern->res);
394 return SUCCESS;
395 }
396 }
397 #if PHP_VERSION_ID >= 80000
398 static ZEND_RESULT_CODE php_pqres_count_elements(zend_object *object, long *count)
399 {
400 return php_pqres_count_elements_ex(object, count);
401 }
402 #else
403 static ZEND_RESULT_CODE php_pqres_count_elements(zval *object, long *count)
404 {
405 return php_pqres_count_elements_ex(Z_OBJ_P(object), count);
406 }
407 #endif
408
409 ZEND_RESULT_CODE php_pqres_success(PGresult *res)
410 {
411 zval zexc, zsqlstate;
412
413 switch (PQresultStatus(res)) {
414 case PGRES_BAD_RESPONSE:
415 case PGRES_NONFATAL_ERROR:
416 case PGRES_FATAL_ERROR:
417 ZVAL_OBJ(&zexc, throw_exce(EX_SQL, "%s", PHP_PQresultErrorMessage(res)));
418 ZVAL_STRING(&zsqlstate, PQresultErrorField(res, PG_DIAG_SQLSTATE));
419 php_pq_update_property(&zexc, "sqlstate", &zsqlstate);
420 zval_ptr_dtor(&zsqlstate);
421 return FAILURE;
422 default:
423 return SUCCESS;
424 }
425 }
426
427 php_pqres_object_t *php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj)
428 {
429 php_pqres_object_t *obj;
430 php_pqres_t *r = ecalloc(1, sizeof(*r));
431
432 r->res = res;
433 zend_hash_init(&r->bound, 0, 0, ZVAL_PTR_DTOR, 0);
434 zend_hash_init(&r->converters, zend_hash_num_elements(&conn_obj->intern->converters), 0, ZVAL_PTR_DTOR, 0);
435 zend_hash_copy(&r->converters, &conn_obj->intern->converters, (copy_ctor_func_t) zval_add_ref);
436
437 r->auto_convert = conn_obj->intern->default_auto_convert;
438 r->default_fetch_type = conn_obj->intern->default_fetch_type;
439
440 obj = php_pqres_create_object_ex(php_pqres_class_entry, r);
441 PQresultSetInstanceData(res, php_pqconn_event, obj);
442
443 return obj;
444 }
445
446 php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res)
447 {
448 return res->iter ? res->iter->fetch_type : res->default_fetch_type;
449 }
450
451 static void php_pqres_object_free(zend_object *o)
452 {
453 php_pqres_object_t *obj = PHP_PQ_OBJ(NULL, o);
454
455 if (obj->intern) {
456 if (obj->intern->res) {
457 PQresultSetInstanceData(obj->intern->res, php_pqconn_event, NULL);
458 PQclear(obj->intern->res);
459 obj->intern->res = NULL;
460 }
461
462 php_pqres_internal_iterator_dtor(obj);
463
464 zend_hash_destroy(&obj->intern->bound);
465 zend_hash_destroy(&obj->intern->converters);
466
467 efree(obj->intern);
468 obj->intern = NULL;
469 }
470 php_pq_object_dtor(o);
471 }
472
473 php_pqres_object_t *php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern)
474 {
475 return php_pq_object_create(ce, intern, sizeof(php_pqres_object_t),
476 &php_pqres_object_handlers, &php_pqres_object_prophandlers);
477 }
478
479 static zend_object *php_pqres_create_object(zend_class_entry *class_type)
480 {
481 return &php_pqres_create_object_ex(class_type, NULL)->zo;
482 }
483
484 static void php_pqres_object_read_status(void *o, zval *return_value)
485 {
486 php_pqres_object_t *obj = o;
487
488 RETVAL_LONG(PQresultStatus(obj->intern->res));
489 }
490
491 static void php_pqres_object_read_status_message(void *o, zval *return_value)
492 {
493 php_pqres_object_t *obj = o;
494
495 RETVAL_STRING(PQresStatus(PQresultStatus(obj->intern->res))+sizeof("PGRES"));
496 }
497
498 static void php_pqres_object_read_error_message(void *o, zval *return_value)
499 {
500 php_pqres_object_t *obj = o;
501 char *error = PHP_PQresultErrorMessage(obj->intern->res);
502
503 if (error) {
504 RETVAL_STRING(error);
505 } else {
506 RETVAL_NULL();
507 }
508 }
509
510 #ifndef PG_DIAG_SEVERITY
511 # define PG_DIAG_SEVERITY 'S'
512 #endif
513 #ifndef PG_DIAG_SQLSTATE
514 # define PG_DIAG_SQLSTATE 'C'
515 #endif
516 #ifndef PG_DIAG_MESSAGE_PRIMARY
517 # define PG_DIAG_MESSAGE_PRIMARY 'M'
518 #endif
519 #ifndef PG_DIAG_MESSAGE_DETAIL
520 # define PG_DIAG_MESSAGE_DETAIL 'D'
521 #endif
522 #ifndef PG_DIAG_MESSAGE_HINT
523 # define PG_DIAG_MESSAGE_HINT 'H'
524 #endif
525 #ifndef PG_DIAG_STATEMENT_POSITION
526 # define PG_DIAG_STATEMENT_POSITION 'P'
527 #endif
528 #ifndef PG_DIAG_INTERNAL_POSITION
529 # define PG_DIAG_INTERNAL_POSITION 'p'
530 #endif
531 #ifndef PG_DIAG_INTERNAL_QUERY
532 # define PG_DIAG_INTERNAL_QUERY 'q'
533 #endif
534 #ifndef PG_DIAG_CONTEXT
535 # define PG_DIAG_CONTEXT 'W'
536 #endif
537 #ifndef PG_DIAG_SCHEMA_NAME
538 # define PG_DIAG_SCHEMA_NAME 's'
539 #endif
540 #ifndef PG_DIAG_TABLE_NAME
541 # define PG_DIAG_TABLE_NAME 't'
542 #endif
543 #ifndef PG_DIAG_COLUMN_NAME
544 # define PG_DIAG_COLUMN_NAME 'c'
545 #endif
546 #ifndef PG_DIAG_DATATYPE_NAME
547 # define PG_DIAG_DATATYPE_NAME 'd'
548 #endif
549 #ifndef PG_DIAG_CONSTRAINT_NAME
550 # define PG_DIAG_CONSTRAINT_NAME 'n'
551 #endif
552 #ifndef PG_DIAG_SOURCE_FILE
553 # define PG_DIAG_SOURCE_FILE 'F'
554 #endif
555 #ifndef PG_DIAG_SOURCE_LINE
556 # define PG_DIAG_SOURCE_LINE 'L'
557 #endif
558 #ifndef PG_DIAG_SOURCE_FUNCTION
559 # define PG_DIAG_SOURCE_FUNCTION 'R'
560 #endif
561
562 static void php_pqres_object_read_diag(void *o, zval *return_value)
563 {
564 php_pqres_object_t *obj = o;
565 int i;
566 struct {
567 char code;
568 const char *const name;
569 } diag[] = {
570 {PG_DIAG_SEVERITY, "severity"},
571 {PG_DIAG_SQLSTATE, "sqlstate"},
572 {PG_DIAG_MESSAGE_PRIMARY, "message_primary"},
573 {PG_DIAG_MESSAGE_DETAIL, "message_detail"},
574 {PG_DIAG_MESSAGE_HINT, "message_hint"},
575 {PG_DIAG_STATEMENT_POSITION,"statement_position"},
576 {PG_DIAG_INTERNAL_POSITION, "internal_position"},
577 {PG_DIAG_INTERNAL_QUERY, "internal_query"},
578 {PG_DIAG_CONTEXT, "context"},
579 {PG_DIAG_SCHEMA_NAME, "schema_name"},
580 {PG_DIAG_TABLE_NAME, "table_name"},
581 {PG_DIAG_COLUMN_NAME, "column_name"},
582 {PG_DIAG_DATATYPE_NAME, "datatype_name"},
583 {PG_DIAG_CONSTRAINT_NAME, "constraint_name"},
584 {PG_DIAG_SOURCE_FILE, "source_file"},
585 {PG_DIAG_SOURCE_LINE, "source_line"},
586 {PG_DIAG_SOURCE_FUNCTION, "source_function"},
587 };
588
589 array_init_size(return_value, 32);
590 for (i = 0; i < sizeof(diag)/sizeof(diag[0]); ++i) {
591 char *value = PQresultErrorField(obj->intern->res, diag[i].code);
592
593 if (value) {
594 add_assoc_string(return_value, diag[i].name, value);
595 } else {
596 add_assoc_null(return_value, diag[i].name);
597 }
598 }
599 }
600
601 static void php_pqres_object_read_num_rows(void *o, zval *return_value)
602 {
603 php_pqres_object_t *obj = o;
604
605 RETVAL_LONG(PQntuples(obj->intern->res));
606 }
607
608 static void php_pqres_object_read_num_cols(void *o, zval *return_value)
609 {
610 php_pqres_object_t *obj = o;
611
612 RETVAL_LONG(PQnfields(obj->intern->res));
613 }
614
615 static void php_pqres_object_read_affected_rows(void *o, zval *return_value)
616 {
617 php_pqres_object_t *obj = o;
618
619 RETVAL_LONG(atoi(PQcmdTuples(obj->intern->res)));
620 }
621
622 static void php_pqres_object_read_fetch_type(void *o, zval *return_value)
623 {
624 php_pqres_object_t *obj = o;
625
626 RETVAL_LONG(php_pqres_fetch_type(obj->intern));
627 }
628
629 static void php_pqres_object_write_fetch_type(void *o, zval *value)
630 {
631 php_pqres_object_t *obj = o;
632
633 if (!obj->intern->iter) {
634 zval object;
635
636 ZVAL_OBJ(&object, &obj->zo);
637 php_pqres_internal_iterator_init(&object);
638 }
639 obj->intern->iter->fetch_type = zval_get_long(value);
640 }
641
642 static void php_pqres_object_read_auto_conv(void *o, zval *return_value)
643 {
644 php_pqres_object_t *obj = o;
645
646 RETVAL_LONG(obj->intern->auto_convert);
647 }
648
649 static void php_pqres_object_write_auto_conv(void *o, zval *value)
650 {
651 php_pqres_object_t *obj = o;
652
653 obj->intern->auto_convert = zval_get_long(value);
654 }
655
656 static ZEND_RESULT_CODE php_pqres_iteration(zval *zobj, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval *row)
657 {
658 ZEND_RESULT_CODE rv;
659 php_pqres_fetch_t orig_fetch;
660
661 if (!obj) {
662 obj = PHP_PQ_OBJ(zobj, NULL);
663 }
664
665 if (obj->intern->iter) {
666 obj->intern->iter->zi.funcs->move_forward((zend_object_iterator *) obj->intern->iter);
667 } else {
668 php_pqres_internal_iterator_init(zobj);
669 }
670 orig_fetch = obj->intern->iter->fetch_type;
671 obj->intern->iter->fetch_type = fetch_type;
672 if (SUCCESS == (rv = obj->intern->iter->zi.funcs->valid((zend_object_iterator *) obj->intern->iter))) {
673 zval *tmp = obj->intern->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->intern->iter);
674 ZVAL_COPY_VALUE(row, tmp);
675 }
676 obj->intern->iter->fetch_type = orig_fetch;
677
678 return rv;
679 }
680
681 typedef struct php_pqres_col {
682 char *name;
683 int num;
684 } php_pqres_col_t;
685
686 static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col)
687 {
688 zend_long index = -1;
689 char *name = NULL;
690
691 if (!zcol) {
692 index = 0;
693 } else {
694 switch (Z_TYPE_P(zcol)) {
695 case IS_NULL:
696 index = 0;
697 break;
698
699 case IS_LONG:
700 index = Z_LVAL_P(zcol);
701 break;
702
703 default:
704 convert_to_string(zcol);
705 /* no break */
706
707 case IS_STRING:
708 if (!is_numeric_string(Z_STRVAL_P(zcol), Z_STRLEN_P(zcol), &index, NULL, 0)) {
709 name = Z_STRVAL_P(zcol);
710 }
711 break;
712 }
713 }
714
715 if (name) {
716 col->name = name;
717 col->num = PQfnumber(obj->intern->res, name);
718 } else {
719 col->name = PQfname(obj->intern->res, index);
720 col->num = index;
721 }
722
723 if (!col->name) {
724 php_error_docref(NULL, E_WARNING, "Failed to find column at index %ld", index);
725 return FAILURE;
726 }
727 if (col->num == -1) {
728 php_error_docref(NULL, E_WARNING, "Failed to find column with name '%s'", name);
729 return FAILURE;
730 }
731 return SUCCESS;
732 }
733
734 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_bind, 0, 0, 2)
735 ZEND_ARG_INFO(0, col)
736 ZEND_ARG_INFO(1, ref)
737 ZEND_END_ARG_INFO();
738 static PHP_METHOD(pqres, bind) {
739 zval *zcol, *zref;
740 zend_error_handling zeh;
741 ZEND_RESULT_CODE rv;
742
743 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
744 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "z/z", &zcol, &zref);
745 zend_restore_error_handling(&zeh);
746
747 if (SUCCESS == rv) {
748 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
749
750 if (!obj->intern) {
751 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
752 } else {
753 php_pqres_col_t col;
754
755 if (SUCCESS != column_nn(obj, zcol, &col)) {
756 RETVAL_FALSE;
757 } else {
758 Z_TRY_ADDREF_P(zref);
759
760 if (!zend_hash_index_update(&obj->intern->bound, col.num, zref)) {
761 php_error_docref(NULL, E_WARNING, "Failed to bind column %s@%d", col.name, col.num);
762 RETVAL_FALSE;
763 } else {
764 zend_hash_sort(&obj->intern->bound, php_pq_compare_index, 0);
765 RETVAL_TRUE;
766 }
767 }
768 }
769 }
770 }
771
772 static int apply_bound(zval *zbound, int argc, va_list argv, zend_hash_key *key)
773 {
774 zval *zvalue;
775 zval *zrow = va_arg(argv, zval *);
776 ZEND_RESULT_CODE *rv = va_arg(argv, ZEND_RESULT_CODE *);
777
778 if (!(zvalue = zend_hash_index_find(Z_ARRVAL_P(zrow), key->h))) {
779 php_error_docref(NULL, E_WARNING, "Failed to find column ad index %lu", key->h);
780 *rv = FAILURE;
781 return ZEND_HASH_APPLY_STOP;
782 } else {
783 ZVAL_DEREF(zbound);
784 zval_dtor(zbound);
785 ZVAL_COPY(zbound, zvalue);
786 *rv = SUCCESS;
787 return ZEND_HASH_APPLY_KEEP;
788 }
789 }
790
791 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_bound, 0, 0, 0)
792 ZEND_END_ARG_INFO();
793 static PHP_METHOD(pqres, fetchBound) {
794 zend_error_handling zeh;
795 ZEND_RESULT_CODE rv;
796
797 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
798 rv = zend_parse_parameters_none();
799 zend_restore_error_handling(&zeh);
800
801 if (SUCCESS == rv) {
802 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
803
804 if (!obj->intern) {
805 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
806 } else {
807 zval row;
808
809 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh);
810 if (SUCCESS == php_pqres_iteration(getThis(), obj, PHP_PQRES_FETCH_ARRAY, &row)) {
811 zend_hash_apply_with_arguments(&obj->intern->bound, apply_bound, 2, &row, &rv);
812
813 if (SUCCESS == rv) {
814 RETVAL_ZVAL(&row, 1, 0);
815 }
816 }
817 zend_restore_error_handling(&zeh);
818 }
819 }
820 }
821
822 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0)
823 ZEND_ARG_INFO(0, fetch_type)
824 ZEND_END_ARG_INFO();
825 static PHP_METHOD(pqres, fetchRow) {
826 zend_error_handling zeh;
827 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
828 zend_long fetch_type = -1;
829 ZEND_RESULT_CODE rv;
830
831 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
832 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &fetch_type);
833 zend_restore_error_handling(&zeh);
834
835 if (SUCCESS == rv) {
836 if (!obj->intern) {
837 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
838 } else {
839 zval row;
840
841 if (fetch_type == -1) {
842 fetch_type = php_pqres_fetch_type(obj->intern);
843 }
844
845 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh);
846 if (SUCCESS == php_pqres_iteration(getThis(), obj, fetch_type, &row)) {
847 RETVAL_ZVAL(&row, 1, 0);
848 }
849 zend_restore_error_handling(&zeh);
850 }
851 }
852 }
853
854 static zval *column_at(zval *row, int col)
855 {
856 zval *data = NULL;
857 HashTable *ht = HASH_OF(row);
858 int count = zend_hash_num_elements(ht);
859
860 if (col >= count) {
861 php_error_docref(NULL, E_WARNING, "Column index %d exceeds column count %d", col, count);
862 } else {
863 zend_hash_internal_pointer_reset(ht);
864 while (col-- > 0) {
865 zend_hash_move_forward(ht);
866 }
867 data = zend_hash_get_current_data(ht);
868 }
869 return data;
870 }
871
872 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 1)
873 ZEND_ARG_INFO(1, ref)
874 ZEND_ARG_INFO(0, col)
875 ZEND_END_ARG_INFO();
876 static PHP_METHOD(pqres, fetchCol) {
877 zend_error_handling zeh;
878 zval *zcol = NULL, *zref;
879 ZEND_RESULT_CODE rv;
880
881 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
882 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "z|z/!", &zref, &zcol);
883 zend_restore_error_handling(&zeh);
884
885 if (SUCCESS == rv) {
886 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
887
888 if (!obj->intern) {
889 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
890 } else {
891 zval row;
892
893 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh);
894 if (SUCCESS == php_pqres_iteration(getThis(), obj, php_pqres_fetch_type(obj->intern), &row)) {
895 php_pqres_col_t col;
896
897 if (SUCCESS != column_nn(obj, zcol, &col)) {
898 RETVAL_FALSE;
899 } else {
900 zval *zres = column_at(&row, col.num);
901
902 if (!zres) {
903 RETVAL_FALSE;
904 } else {
905 ZVAL_DEREF(zref);
906 zval_dtor(zref);
907 ZVAL_ZVAL(zref, zres, 1, 0);
908 RETVAL_TRUE;
909 }
910 }
911 }
912 zend_restore_error_handling(&zeh);
913 }
914 }
915 }
916
917 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all_cols, 0, 0, 0)
918 ZEND_ARG_INFO(0, col)
919 ZEND_END_ARG_INFO();
920 static PHP_METHOD(pqres, fetchAllCols) {
921 zend_error_handling zeh;
922 zval *zcol = NULL;
923 ZEND_RESULT_CODE rv;
924
925 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
926 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|z!", &zcol);
927 zend_restore_error_handling(&zeh);
928
929 if (SUCCESS == rv) {
930 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
931
932 if (!obj->intern) {
933 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
934 } else {
935 php_pqres_col_t col;
936
937 zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh);
938 if (SUCCESS == column_nn(obj, zcol, &col)) {
939 int r, rows = PQntuples(obj->intern->res);
940 zval tmp;
941
942 array_init(return_value);
943 for (r = 0; r < rows; ++r) {
944 add_next_index_zval(return_value, php_pqres_get_col(obj->intern, r, col.num, &tmp));
945 }
946 }
947 zend_restore_error_handling(&zeh);
948 }
949 }
950 }
951
952 struct apply_to_col_arg {
953 php_pqres_object_t *obj;
954 php_pqres_col_t *cols;
955 ZEND_RESULT_CODE status;
956 };
957
958 static int apply_to_col(zval *c, void *a)
959 {
960 struct apply_to_col_arg *arg = a;
961
962 if (SUCCESS != column_nn(arg->obj, c, arg->cols)) {
963 arg->status = FAILURE;
964 return ZEND_HASH_APPLY_STOP;
965 } else {
966 arg->status = SUCCESS;
967 ++arg->cols;
968 return ZEND_HASH_APPLY_KEEP;
969 }
970 }
971
972 static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashTable *ht)
973 {
974 struct apply_to_col_arg arg = {NULL};
975 php_pqres_col_t *tmp;
976
977 arg.obj = obj;
978 arg.cols = ecalloc(zend_hash_num_elements(ht), sizeof(*tmp));
979 tmp = arg.cols;
980 zend_hash_apply_with_argument(ht, apply_to_col, &arg);
981
982 if (SUCCESS == arg.status) {
983 return tmp;
984 } else {
985 efree(tmp);
986 return NULL;
987 }
988 }
989
990 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_map, 0, 0, 0)
991 ZEND_ARG_INFO(0, keys)
992 ZEND_ARG_INFO(0, vals)
993 ZEND_ARG_INFO(0, fetch_type)
994 ZEND_END_ARG_INFO();
995 static PHP_METHOD(pqres, map) {
996 zend_error_handling zeh;
997 zval *zkeys = 0, *zvals = 0;
998 zend_long fetch_type = -1;
999 ZEND_RESULT_CODE rv;
1000
1001 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1002 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|z/!z/!l", &zkeys, &zvals, &fetch_type);
1003 zend_restore_error_handling(&zeh);
1004
1005 if (SUCCESS == rv) {
1006 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1007
1008 if (!obj->intern) {
1009 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
1010 } else {
1011 int ks = 0, vs = 0;
1012 php_pqres_col_t def = {PQfname(obj->intern->res, 0), 0}, *keys = NULL, *vals = NULL;
1013
1014 if (zkeys) {
1015 convert_to_array(zkeys);
1016
1017 if ((ks = zend_hash_num_elements(Z_ARRVAL_P(zkeys)))) {
1018 keys = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zkeys));
1019 } else {
1020 ks = 1;
1021 keys = &def;
1022 }
1023 } else {
1024 ks = 1;
1025 keys = &def;
1026 }
1027 if (zvals) {
1028 convert_to_array(zvals);
1029
1030 if ((vs = zend_hash_num_elements(Z_ARRVAL_P(zvals)))) {
1031 vals = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zvals));
1032 }
1033 }
1034
1035 if (fetch_type == -1) {
1036 fetch_type = php_pqres_fetch_type(obj->intern);
1037 }
1038
1039 if (keys) {
1040 int rows, r;
1041 zval *cur;
1042
1043 switch (fetch_type) {
1044 case PHP_PQRES_FETCH_ARRAY:
1045 case PHP_PQRES_FETCH_ASSOC:
1046 array_init(return_value);
1047 break;
1048 case PHP_PQRES_FETCH_OBJECT:
1049 object_init(return_value);
1050 break;
1051 }
1052 for (r = 0, rows = PQntuples(obj->intern->res); r < rows; ++r) {
1053 int k, v;
1054 zval *ptr;
1055
1056 cur = return_value;
1057 for (k = 0; k < ks; ++k) {
1058 char *key = PQgetvalue(obj->intern->res, r, keys[k].num);
1059 int len = PQgetlength(obj->intern->res, r, keys[k].num);
1060
1061 if (!(ptr = zend_symtable_str_find(HASH_OF(cur), key, len))) {
1062 zval tmp;
1063
1064 switch (fetch_type) {
1065 case PHP_PQRES_FETCH_ARRAY:
1066 case PHP_PQRES_FETCH_ASSOC:
1067 array_init(&tmp);
1068 break;
1069 case PHP_PQRES_FETCH_OBJECT:
1070 object_init(&tmp);
1071 break;
1072 }
1073 if (!(ptr = zend_symtable_str_update(HASH_OF(cur), key, len, &tmp))) {
1074 throw_exce(EX_RUNTIME, "Failed to create map");
1075 goto err;
1076 }
1077 cur = ptr;
1078 }
1079 cur = ptr;
1080 }
1081 if (vals && vs) {
1082 for (v = 0; v < vs; ++v) {
1083 char *val = PQgetvalue(obj->intern->res, r, vals[v].num);
1084 int len = PQgetlength(obj->intern->res, r, vals[v].num);
1085
1086 switch (fetch_type) {
1087 case PHP_PQRES_FETCH_ARRAY:
1088 add_index_stringl(cur, vals[v].num, val, len);
1089 break;
1090 case PHP_PQRES_FETCH_ASSOC:
1091 add_assoc_stringl(cur, vals[v].name, val, len);
1092 break;
1093 case PHP_PQRES_FETCH_OBJECT:
1094 add_property_stringl(cur, vals[v].name, val, len);
1095 break;
1096 }
1097 }
1098 } else {
1099 php_pqres_row_to_zval(obj->intern->res, r, fetch_type, cur);
1100 }
1101 }
1102 }
1103
1104 err:
1105 if (keys && keys != &def) {
1106 efree(keys);
1107 }
1108 if (vals) {
1109 efree(vals);
1110 }
1111 }
1112 }
1113 }
1114
1115 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all, 0, 0, 0)
1116 ZEND_ARG_INFO(0, fetch_type)
1117 ZEND_END_ARG_INFO();
1118 static PHP_METHOD(pqres, fetchAll) {
1119 zend_error_handling zeh;
1120 zend_long fetch_type = -1;
1121 ZEND_RESULT_CODE rv;
1122
1123 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1124 rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &fetch_type);
1125 zend_restore_error_handling(&zeh);
1126
1127 if (SUCCESS == rv) {
1128 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1129
1130 if (!obj->intern) {
1131 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
1132 } else {
1133 int r, rows = PQntuples(obj->intern->res);
1134 zval tmp;
1135
1136 if (fetch_type == -1) {
1137 fetch_type = php_pqres_fetch_type(obj->intern);
1138 }
1139
1140 array_init(return_value);
1141 for (r = 0; r < rows; ++r) {
1142 ZVAL_NULL(&tmp);
1143 add_next_index_zval(return_value, php_pqres_row_to_zval(obj->intern->res, r, fetch_type, &tmp));
1144 }
1145 }
1146 }
1147 }
1148
1149 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_count, 0, 0, 0)
1150 ZEND_END_ARG_INFO();
1151 static PHP_METHOD(pqres, count) {
1152 zend_error_handling zeh;
1153 ZEND_RESULT_CODE rv;
1154
1155 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1156 rv = zend_parse_parameters_none();
1157 zend_restore_error_handling(&zeh);
1158
1159 if (SUCCESS == rv) {
1160 long count;
1161
1162 if (SUCCESS != php_pqres_count_elements_ex(Z_OBJ_P(getThis()), &count)) {
1163 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
1164 } else {
1165 RETVAL_LONG(count);
1166 }
1167 }
1168 }
1169
1170 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_desc, 0, 0, 0)
1171 ZEND_END_ARG_INFO();
1172 static PHP_METHOD(pqres, desc) {
1173 zend_error_handling zeh;
1174 ZEND_RESULT_CODE rv;
1175
1176 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1177 rv = zend_parse_parameters_none();
1178 zend_restore_error_handling(&zeh);
1179
1180 if (SUCCESS == rv) {
1181 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1182
1183 if (!obj->intern) {
1184 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
1185 } else {
1186 int p, params;
1187
1188 array_init(return_value);
1189 for (p = 0, params = PQnparams(obj->intern->res); p < params; ++p) {
1190 add_next_index_long(return_value, PQparamtype(obj->intern->res, p));
1191 }
1192 }
1193 }
1194 }
1195
1196 #if PHP_VERSION_ID >= 80000
1197 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_getIterator, 0, 0, 0)
1198 ZEND_END_ARG_INFO();
1199 static PHP_METHOD(pqres, getIterator)
1200 {
1201 zend_error_handling zeh;
1202 ZEND_RESULT_CODE rv;
1203
1204 zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
1205 rv = zend_parse_parameters_none();
1206 zend_restore_error_handling(&zeh);
1207
1208 if (SUCCESS == rv) {
1209 php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
1210
1211 if (!obj->intern) {
1212 throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized");
1213 } else {
1214 zend_create_internal_iterator_zval(return_value, getThis());
1215 }
1216 }
1217 }
1218 #endif
1219
1220 static zend_function_entry php_pqres_methods[] = {
1221 PHP_ME(pqres, bind, ai_pqres_bind, ZEND_ACC_PUBLIC)
1222 PHP_ME(pqres, fetchBound, ai_pqres_fetch_bound, ZEND_ACC_PUBLIC)
1223 PHP_ME(pqres, fetchRow, ai_pqres_fetch_row, ZEND_ACC_PUBLIC)
1224 PHP_ME(pqres, fetchCol, ai_pqres_fetch_col, ZEND_ACC_PUBLIC)
1225 PHP_ME(pqres, fetchAll, ai_pqres_fetch_all, ZEND_ACC_PUBLIC)
1226 PHP_ME(pqres, fetchAllCols, ai_pqres_fetch_all_cols, ZEND_ACC_PUBLIC)
1227 PHP_ME(pqres, count, ai_pqres_count, ZEND_ACC_PUBLIC)
1228 PHP_ME(pqres, map, ai_pqres_map, ZEND_ACC_PUBLIC)
1229 PHP_ME(pqres, desc, ai_pqres_desc, ZEND_ACC_PUBLIC)
1230 #if PHP_VERSION_ID >= 80000
1231 PHP_ME(pqres, getIterator, ai_pqres_getIterator, ZEND_ACC_PUBLIC)
1232 #endif
1233 {0}
1234 };
1235
1236 PHP_MSHUTDOWN_FUNCTION(pqres)
1237 {
1238 zend_hash_destroy(&php_pqres_object_prophandlers);
1239 return SUCCESS;
1240 }
1241
1242 PHP_MINIT_FUNCTION(pqres)
1243 {
1244 zend_class_entry ce = {0};
1245 php_pq_object_prophandler_t ph = {0};
1246
1247 INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods);
1248 php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL);
1249 php_pqres_class_entry->create_object = php_pqres_create_object;
1250 php_pqres_class_entry->get_iterator = php_pqres_iterator_init;
1251 #if PHP_VERSION_ID >= 80000
1252 zend_class_implements(php_pqres_class_entry, 2, zend_ce_aggregate, zend_ce_countable);
1253 #else
1254 zend_class_implements(php_pqres_class_entry, 2, zend_ce_traversable, zend_ce_countable);
1255 #endif
1256
1257 memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1258 php_pqres_object_handlers.offset = XtOffsetOf(php_pqres_object_t, zo);
1259 php_pqres_object_handlers.free_obj = php_pqres_object_free;
1260 php_pqres_object_handlers.read_property = php_pq_object_read_prop;
1261 php_pqres_object_handlers.write_property = php_pq_object_write_prop;
1262 php_pqres_object_handlers.clone_obj = NULL;
1263 php_pqres_object_handlers.get_property_ptr_ptr = php_pq_object_get_prop_ptr_null;
1264 php_pqres_object_handlers.get_gc = php_pq_object_get_gc;
1265 php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info;
1266 php_pqres_object_handlers.get_properties = php_pq_object_properties;
1267 php_pqres_object_handlers.count_elements = php_pqres_count_elements;
1268
1269 zend_hash_init(&php_pqres_object_prophandlers, 9, NULL, php_pq_object_prophandler_dtor, 1);
1270
1271 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC);
1272 ph.read = php_pqres_object_read_status;
1273 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "status", sizeof("status")-1, (void *) &ph, sizeof(ph));
1274
1275 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("statusMessage"), ZEND_ACC_PUBLIC);
1276 ph.read = php_pqres_object_read_status_message;
1277 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "statusMessage", sizeof("statusMessage")-1, (void *) &ph, sizeof(ph));
1278
1279 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC);
1280 ph.read = php_pqres_object_read_error_message;
1281 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage")-1, (void *) &ph, sizeof(ph));
1282
1283 zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("diag"), ZEND_ACC_PUBLIC);
1284 ph.read = php_pqres_object_read_diag;
1285 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "diag", sizeof("diag")-1, (void *) &ph, sizeof(ph));
1286
1287 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC);
1288 ph.read = php_pqres_object_read_num_rows;
1289 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "numRows", sizeof("numRows")-1, (void *) &ph, sizeof(ph));
1290
1291 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC);
1292 ph.read = php_pqres_object_read_num_cols;
1293 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "numCols", sizeof("numCols")-1, (void *) &ph, sizeof(ph));
1294
1295 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC);
1296 ph.read = php_pqres_object_read_affected_rows;
1297 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows")-1, (void *) &ph, sizeof(ph));
1298
1299 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC);
1300 ph.read = php_pqres_object_read_fetch_type;
1301 ph.write = php_pqres_object_write_fetch_type;
1302 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType")-1, (void *) &ph, sizeof(ph));
1303 ph.write = NULL;
1304
1305 zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("autoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC);
1306 ph.read = php_pqres_object_read_auto_conv;
1307 ph.write = php_pqres_object_write_auto_conv;
1308 zend_hash_str_add_mem(&php_pqres_object_prophandlers, "autoConvert", sizeof("autoConvert")-1, (void *) &ph, sizeof(ph));
1309 ph.write = NULL;
1310
1311 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY);
1312 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK);
1313 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK);
1314 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT);
1315 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN);
1316 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE);
1317 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR);
1318 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR);
1319 #ifdef HAVE_PGRES_COPY_BOTH
1320 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH);
1321 #endif
1322 #ifdef HAVE_PGRES_SINGLE_TUPLE
1323 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE);
1324 #endif
1325
1326 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY);
1327 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC);
1328 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT);
1329
1330 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_BOOL"), PHP_PQRES_CONV_BOOL);
1331 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_INT"), PHP_PQRES_CONV_INT);
1332 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_FLOAT"), PHP_PQRES_CONV_FLOAT);
1333 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR);
1334 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY);
1335 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME);
1336 #if PHP_PQ_HAVE_PHP_JSON_H
1337 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON);
1338 #endif
1339 zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL);
1340
1341 return SUCCESS;
1342 }
1343
1344 /*
1345 * Local variables:
1346 * tab-width: 4
1347 * c-basic-offset: 4
1348 * End:
1349 * vim600: noet sw=4 ts=4 fdm=marker
1350 * vim<600: noet sw=4 ts=4
1351 */