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 +--------------------------------------------------------------------+
19 #define SMART_STR_PREALLOC 256
20 #include <ext/standard/php_smart_str.h>
22 #include <libpq-events.h>
26 #include "php_pq_misc.h"
27 #include "php_pq_object.h"
28 #include "php_pqexc.h"
29 #include "php_pqconn.h"
30 #include "php_pqconn_event.h"
31 #include "php_pqres.h"
32 #include "php_pqstm.h"
33 #include "php_pqtxn.h"
34 #include "php_pqcur.h"
36 zend_class_entry
*php_pqconn_class_entry
;
37 static zend_object_handlers php_pqconn_object_handlers
;
38 static HashTable php_pqconn_object_prophandlers
;
41 static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id TSRMLS_DC)
45 if (SUCCESS == zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) {
46 zend_hash_index_del(Z_ARRVAL_PP(evhs), id);
51 static ulong
php_pqconn_add_eventhandler(php_pqconn_object_t
*obj
, const char *type_str
, size_t type_len
, php_pq_callback_t
*cb TSRMLS_DC
)
56 if (SUCCESS
!= zend_hash_find(&obj
->intern
->eventhandlers
, type_str
, type_len
+ 1, (void *) &evhs
)) {
59 zend_hash_init(&evh
, 1, NULL
, (dtor_func_t
) php_pq_callback_dtor
, 0);
60 zend_hash_add(&obj
->intern
->eventhandlers
, type_str
, type_len
+ 1, (void *) &evh
, sizeof(evh
), (void *) &evhs
);
63 php_pq_callback_addref(cb
);
64 h
= zend_hash_next_free_element(evhs
);
65 zend_hash_index_update(evhs
, h
, (void *) cb
, sizeof(*cb
), NULL
);
70 static void php_pqconn_object_free(void *o TSRMLS_DC
)
72 php_pqconn_object_t
*obj
= o
;
74 fprintf(stderr
, "FREE conn(#%d) %p\n", obj
->zv
.handle
, obj
);
77 php_pq_callback_dtor(&obj
->intern
->onevent
);
78 php_resource_factory_handle_dtor(&obj
->intern
->factory
, obj
->intern
->conn TSRMLS_CC
);
79 php_resource_factory_dtor(&obj
->intern
->factory
);
80 zend_hash_destroy(&obj
->intern
->listeners
);
81 zend_hash_destroy(&obj
->intern
->statements
);
82 zend_hash_destroy(&obj
->intern
->converters
);
83 zend_hash_destroy(&obj
->intern
->eventhandlers
);
87 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
92 zend_object_value
php_pqconn_create_object_ex(zend_class_entry
*ce
, php_pqconn_t
*intern
, php_pqconn_object_t
**ptr TSRMLS_DC
)
94 php_pqconn_object_t
*o
;
96 o
= ecalloc(1, sizeof(*o
));
97 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
98 object_properties_init((zend_object
*) o
, ce
);
99 o
->prophandler
= &php_pqconn_object_prophandlers
;
109 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqconn_object_free
, NULL TSRMLS_CC
);
110 o
->zv
.handlers
= &php_pqconn_object_handlers
;
115 static zend_object_value
php_pqconn_create_object(zend_class_entry
*class_type TSRMLS_DC
)
117 return php_pqconn_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
120 static void php_pqconn_object_read_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
122 php_pqconn_object_t
*obj
= o
;
124 RETVAL_LONG(PQstatus(obj
->intern
->conn
));
127 static void php_pqconn_object_read_transaction_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
129 php_pqconn_object_t
*obj
= o
;
131 RETVAL_LONG(PQtransactionStatus(obj
->intern
->conn
));
134 static void php_pqconn_object_read_error_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
136 php_pqconn_object_t
*obj
= o
;
137 char *error
= PHP_PQerrorMessage(obj
->intern
->conn
);
140 RETVAL_STRING(error
, 1);
146 static int apply_notify_listener(void *p
, void *arg TSRMLS_DC
)
148 php_pq_callback_t
*listener
= p
;
150 zval
*zpid
, *zchannel
, *zmessage
;
153 ZVAL_LONG(zpid
, nfy
->be_pid
);
154 MAKE_STD_ZVAL(zchannel
);
155 ZVAL_STRING(zchannel
, nfy
->relname
, 1);
156 MAKE_STD_ZVAL(zmessage
);
157 ZVAL_STRING(zmessage
, nfy
->extra
, 1);
159 zend_fcall_info_argn(&listener
->fci TSRMLS_CC
, 3, &zchannel
, &zmessage
, &zpid
);
160 zend_fcall_info_call(&listener
->fci
, &listener
->fcc
, NULL
, NULL TSRMLS_CC
);
162 zval_ptr_dtor(&zchannel
);
163 zval_ptr_dtor(&zmessage
);
164 zval_ptr_dtor(&zpid
);
166 return ZEND_HASH_APPLY_KEEP
;
169 static int apply_notify_listeners(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
171 HashTable
*listeners
= p
;
172 PGnotify
*nfy
= va_arg(argv
, PGnotify
*);
174 if (0 == fnmatch(key
->arKey
, nfy
->relname
, 0)) {
175 zend_hash_apply_with_argument(listeners
, apply_notify_listener
, nfy TSRMLS_CC
);
178 return ZEND_HASH_APPLY_KEEP
;
181 void php_pqconn_notify_listeners(php_pqconn_object_t
*obj TSRMLS_DC
)
185 while ((nfy
= PQnotifies(obj
->intern
->conn
))) {
186 zend_hash_apply_with_arguments(&obj
->intern
->listeners TSRMLS_CC
, apply_notify_listeners
, 1, nfy
);
191 static void php_pqconn_object_read_busy(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
193 php_pqconn_object_t
*obj
= o
;
195 RETVAL_BOOL(PQisBusy(obj
->intern
->conn
));
198 static void php_pqconn_object_read_encoding(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
200 php_pqconn_object_t
*obj
= o
;
202 RETVAL_STRING(pg_encoding_to_char(PQclientEncoding(obj
->intern
->conn
)), 1);
205 static void php_pqconn_object_write_encoding(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
207 php_pqconn_object_t
*obj
= o
;
210 if (Z_TYPE_P(value
) != IS_STRING
) {
211 if (Z_REFCOUNT_P(value
) > 1) {
214 ZVAL_ZVAL(tmp
, zenc
, 1, 0);
215 convert_to_string(tmp
);
218 convert_to_string_ex(&zenc
);
222 if (0 > PQsetClientEncoding(obj
->intern
->conn
, Z_STRVAL_P(zenc
))) {
223 php_error(E_NOTICE
, "Unrecognized encoding '%s'", Z_STRVAL_P(zenc
));
227 zval_ptr_dtor(&zenc
);
231 static void php_pqconn_object_read_unbuffered(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
233 php_pqconn_object_t
*obj
= o
;
235 RETVAL_BOOL(obj
->intern
->unbuffered
);
238 static void php_pqconn_object_write_unbuffered(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
240 php_pqconn_object_t
*obj
= o
;
242 obj
->intern
->unbuffered
= z_is_true(value
);
245 static void php_pqconn_object_read_nonblocking(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
247 php_pqconn_object_t
*obj
= o
;
249 RETVAL_BOOL(PQisnonblocking(obj
->intern
->conn
));
252 static void php_pqconn_object_write_nonblocking(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
254 php_pqconn_object_t
*obj
= o
;
256 PQsetnonblocking(obj
->intern
->conn
, z_is_true(value
));
259 static void php_pqconn_object_read_db(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
261 php_pqconn_object_t
*obj
= o
;
262 char *db
= PQdb(obj
->intern
->conn
);
265 RETVAL_STRING(db
, 1);
267 RETVAL_EMPTY_STRING();
271 static void php_pqconn_object_read_user(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
273 php_pqconn_object_t
*obj
= o
;
274 char *user
= PQuser(obj
->intern
->conn
);
277 RETVAL_STRING(user
, 1);
279 RETVAL_EMPTY_STRING();
283 static void php_pqconn_object_read_pass(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
285 php_pqconn_object_t
*obj
= o
;
286 char *pass
= PQpass(obj
->intern
->conn
);
289 RETVAL_STRING(pass
, 1);
291 RETVAL_EMPTY_STRING();
295 static void php_pqconn_object_read_host(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
297 php_pqconn_object_t
*obj
= o
;
298 char *host
= PQhost(obj
->intern
->conn
);
301 RETVAL_STRING(host
, 1);
303 RETVAL_EMPTY_STRING();
307 static void php_pqconn_object_read_port(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
309 php_pqconn_object_t
*obj
= o
;
310 char *port
= PQport(obj
->intern
->conn
);
313 RETVAL_STRING(port
, 1);
315 RETVAL_EMPTY_STRING();
320 static void php_pqconn_object_read_params(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
322 php_pqconn_object_t
*obj
= o
;
323 PQconninfoOption
*ptr
, *params
= PQconninfo(obj
->intern
->conn
);
325 array_init(return_value
);
328 for (ptr
= params
; ptr
->keyword
; ++ptr
) {
330 add_assoc_string(return_value
, ptr
->keyword
, ptr
->val
, 1);
332 add_assoc_null(return_value
, ptr
->keyword
);
335 PQconninfoFree(params
);
340 static void php_pqconn_object_read_options(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
342 php_pqconn_object_t
*obj
= o
;
343 char *options
= PQoptions(obj
->intern
->conn
);
346 RETVAL_STRING(options
, 1);
348 RETVAL_EMPTY_STRING();
352 static int apply_read_event_handler_ex(void *p
, void *arg TSRMLS_DC
)
355 zval
*zcb
= php_pq_callback_to_zval(p
);
357 zend_hash_next_index_insert(rv
, &zcb
, sizeof(zval
*), NULL
);
359 return ZEND_HASH_APPLY_KEEP
;
362 static int apply_read_event_handlers(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
364 HashTable
*evhs
= p
, *rv
= va_arg(argv
, HashTable
*);
365 zval
*entry
, **entry_ptr
;
367 MAKE_STD_ZVAL(entry
);
368 array_init_size(entry
, zend_hash_num_elements(evhs
));
370 if (key
->nKeyLength
) {
371 zend_hash_add(rv
, key
->arKey
, key
->nKeyLength
, &entry
, sizeof(zval
*), (void *) &entry_ptr
);
373 zend_hash_index_update(rv
, key
->h
, &entry
, sizeof(zval
*), (void *) &entry_ptr
);
376 zend_hash_apply_with_argument(evhs
, apply_read_event_handler_ex
, Z_ARRVAL_PP(entry_ptr
) TSRMLS_CC
);
378 return ZEND_HASH_APPLY_KEEP
;
380 static void php_pqconn_object_read_event_handlers(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
382 php_pqconn_object_t
*obj
= o
;
384 array_init(return_value
);
385 zend_hash_apply_with_arguments(&obj
->intern
->eventhandlers TSRMLS_CC
, apply_read_event_handlers
, 1, Z_ARRVAL_P(return_value
) TSRMLS_CC
);
388 static void php_pqconn_object_read_def_fetch_type(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
390 php_pqconn_object_t
*obj
= o
;
392 RETVAL_LONG(obj
->intern
->default_fetch_type
);
394 static void php_pqconn_object_write_def_fetch_type(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
396 php_pqconn_object_t
*obj
= o
;
399 if (Z_TYPE_P(zft
) != IS_LONG
) {
400 if (Z_REFCOUNT_P(zft
) > 1) {
403 ZVAL_ZVAL(tmp
, zft
, 1, 0);
404 convert_to_long(tmp
);
407 convert_to_long_ex(&zft
);
411 obj
->intern
->default_fetch_type
= Z_LVAL_P(zft
) & 0x3; /* two bits only */
418 static void php_pqconn_object_read_def_txn_isolation(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
420 php_pqconn_object_t
*obj
= o
;
422 RETVAL_LONG(obj
->intern
->default_txn_isolation
);
424 static void php_pqconn_object_write_def_txn_isolation(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
426 php_pqconn_object_t
*obj
= o
;
429 if (Z_TYPE_P(zti
) != IS_LONG
) {
430 if (Z_REFCOUNT_P(zti
) > 1) {
433 ZVAL_ZVAL(tmp
, zti
, 1, 0);
434 convert_to_long(tmp
);
437 convert_to_long_ex(&zti
);
441 obj
->intern
->default_txn_isolation
= Z_LVAL_P(zti
) & 0x3; /* two bits only */
448 static void php_pqconn_object_read_def_txn_readonly(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
450 php_pqconn_object_t
*obj
= o
;
452 RETVAL_BOOL(obj
->intern
->default_txn_readonly
);
454 static void php_pqconn_object_write_def_txn_readonly(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
456 php_pqconn_object_t
*obj
= o
;
458 obj
->intern
->default_txn_readonly
= zend_is_true(value
);
461 static void php_pqconn_object_read_def_txn_deferrable(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
463 php_pqconn_object_t
*obj
= o
;
465 RETVAL_BOOL(obj
->intern
->default_txn_deferrable
);
467 static void php_pqconn_object_write_def_txn_deferrable(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
469 php_pqconn_object_t
*obj
= o
;
471 obj
->intern
->default_txn_deferrable
= zend_is_true(value
);
474 static void php_pqconn_object_read_def_auto_conv(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
476 php_pqconn_object_t
*obj
= o
;
478 RETVAL_LONG(obj
->intern
->default_auto_convert
);
480 static void php_pqconn_object_write_def_auto_conv(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
482 php_pqconn_object_t
*obj
= o
;
485 if (Z_TYPE_P(zac
) != IS_LONG
) {
486 if (Z_REFCOUNT_P(zac
) > 1) {
489 ZVAL_ZVAL(tmp
, zac
, 1, 0);
490 convert_to_long(tmp
);
493 convert_to_long_ex(&zac
);
497 obj
->intern
->default_auto_convert
= Z_LVAL_P(zac
) & PHP_PQRES_CONV_ALL
;
504 static ZEND_RESULT_CODE
php_pqconn_update_socket(zval
*this_ptr
, php_pqconn_object_t
*obj TSRMLS_DC
)
506 zval
*zsocket
, zmember
;
508 ZEND_RESULT_CODE retval
;
512 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
515 INIT_PZVAL(&zmember
);
516 ZVAL_STRINGL(&zmember
, "socket", sizeof("socket")-1, 0);
517 MAKE_STD_ZVAL(zsocket
);
519 if ((CONNECTION_BAD
!= PQstatus(obj
->intern
->conn
))
520 && (-1 < (socket
= PQsocket(obj
->intern
->conn
)))
521 && (stream
= php_stream_fopen_from_fd(socket
, "r+b", NULL
))) {
522 stream
->flags
|= PHP_STREAM_FLAG_NO_CLOSE
;
523 php_stream_to_zval(stream
, zsocket
);
529 zend_get_std_object_handlers()->write_property(getThis(), &zmember
, zsocket
, NULL TSRMLS_CC
);
530 zval_ptr_dtor(&zsocket
);
535 static void *php_pqconn_resource_factory_ctor(void *data
, void *init_arg TSRMLS_DC
)
537 php_pqconn_resource_factory_data_t
*o
= init_arg
;
538 PGconn
*conn
= NULL
;;
540 if (o
->flags
& PHP_PQCONN_ASYNC
) {
541 conn
= PQconnectStart(o
->dsn
);
543 conn
= PQconnectdb(o
->dsn
);
547 PQregisterEventProc(conn
, php_pqconn_event
, "ext-pq", NULL
);
553 static void php_pqconn_resource_factory_dtor(void *opaque
, void *handle TSRMLS_DC
)
555 php_pqconn_event_data_t
*evdata
= PQinstanceData(handle
, php_pqconn_event
);
557 /* we don't care for anything, except free'ing evdata */
559 PQsetInstanceData(handle
, php_pqconn_event
, NULL
);
560 memset(evdata
, 0, sizeof(*evdata
));
567 static php_resource_factory_ops_t php_pqconn_resource_factory_ops
= {
568 php_pqconn_resource_factory_ctor
,
570 php_pqconn_resource_factory_dtor
573 php_resource_factory_ops_t
*php_pqconn_get_resource_factory_ops(void)
575 return &php_pqconn_resource_factory_ops
;
578 static void php_pqconn_wakeup(php_persistent_handle_factory_t
*f
, void **handle TSRMLS_DC
)
580 PGresult
*res
= PQexec(*handle
, "");
581 php_pqres_clear(res
);
583 if (CONNECTION_OK
!= PQstatus(*handle
)) {
588 static inline PGresult
*unlisten(PGconn
*conn
, const char *channel_str
, size_t channel_len TSRMLS_DC
)
590 char *quoted_channel
= PQescapeIdentifier(conn
, channel_str
, channel_len
);
591 PGresult
*res
= NULL
;
593 if (quoted_channel
) {
596 smart_str_appends(&cmd
, "UNLISTEN ");
597 smart_str_appends(&cmd
, quoted_channel
);
600 res
= PQexec(conn
, cmd
.c
);
602 smart_str_free(&cmd
);
603 PQfreemem(quoted_channel
);
609 static int apply_unlisten(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
611 php_pqconn_object_t
*obj
= va_arg(argv
, php_pqconn_object_t
*);
612 PGresult
*res
= unlisten(obj
->intern
->conn
, key
->arKey
, key
->nKeyLength
- 1 TSRMLS_CC
);
615 php_pqres_clear(res
);
618 return ZEND_HASH_APPLY_REMOVE
;
621 static void php_pqconn_retire(php_persistent_handle_factory_t
*f
, void **handle TSRMLS_DC
)
623 php_pqconn_event_data_t
*evdata
= PQinstanceData(*handle
, php_pqconn_event
);
628 PQsetInstanceData(*handle
, php_pqconn_event
, NULL
);
631 PQsetNoticeReceiver(*handle
, php_pqconn_notice_ignore
, NULL
);
633 /* cancel async queries */
634 if (PQisBusy(*handle
) && (cancel
= PQgetCancel(*handle
))) {
637 PQcancel(cancel
, err
, sizeof(err
));
638 PQfreeCancel(cancel
);
640 /* clean up async results */
641 while ((res
= PQgetResult(*handle
))) {
642 php_pqres_clear(res
);
645 /* clean up transaction & session */
646 switch (PQtransactionStatus(*handle
)) {
648 res
= PQexec(*handle
, "RESET ALL");
651 res
= PQexec(*handle
, "ROLLBACK; RESET ALL");
656 php_pqres_clear(res
);
660 /* clean up notify listeners */
661 zend_hash_apply_with_arguments(&evdata
->obj
->intern
->listeners TSRMLS_CC
, apply_unlisten
, 1, evdata
->obj
);
663 /* release instance data */
668 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct
, 0, 0, 1)
669 ZEND_ARG_INFO(0, dsn
)
670 ZEND_ARG_INFO(0, flags
)
672 static PHP_METHOD(pqconn
, __construct
) {
673 zend_error_handling zeh
;
679 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
680 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|sl", &dsn_str
, &dsn_len
, &flags
);
681 zend_restore_error_handling(&zeh TSRMLS_CC
);
684 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
687 throw_exce(EX_BAD_METHODCALL TSRMLS_CC
, "pq\\Connection already initialized");
689 php_pqconn_event_data_t
*evdata
= php_pqconn_event_data_init(obj TSRMLS_CC
);
690 php_pqconn_resource_factory_data_t rfdata
= {dsn_str
, flags
};
692 obj
->intern
= ecalloc(1, sizeof(*obj
->intern
));
694 obj
->intern
->default_auto_convert
= PHP_PQRES_CONV_ALL
;
696 zend_hash_init(&obj
->intern
->listeners
, 0, NULL
, (dtor_func_t
) zend_hash_destroy
, 0);
697 zend_hash_init(&obj
->intern
->statements
, 0, NULL
, NULL
, 0);
698 zend_hash_init(&obj
->intern
->converters
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
699 zend_hash_init(&obj
->intern
->eventhandlers
, 0, NULL
, (dtor_func_t
) zend_hash_destroy
, 0);
701 if (flags
& PHP_PQCONN_PERSISTENT
) {
702 php_persistent_handle_factory_t
*phf
= php_persistent_handle_concede(NULL
, ZEND_STRL("pq\\Connection"), dsn_str
, dsn_len
, php_pqconn_wakeup
, php_pqconn_retire TSRMLS_CC
);
703 php_persistent_handle_resource_factory_init(&obj
->intern
->factory
, phf
);
705 php_resource_factory_init(&obj
->intern
->factory
, &php_pqconn_resource_factory_ops
, NULL
, NULL
);
708 if (flags
& PHP_PQCONN_ASYNC
) {
709 obj
->intern
->poller
= (int (*)(PGconn
*)) PQconnectPoll
;
712 obj
->intern
->conn
= php_resource_factory_handle_ctor(&obj
->intern
->factory
, &rfdata TSRMLS_CC
);
714 PQsetInstanceData(obj
->intern
->conn
, php_pqconn_event
, evdata
);
715 PQsetNoticeReceiver(obj
->intern
->conn
, php_pqconn_notice_recv
, evdata
);
717 if (SUCCESS
!= php_pqconn_update_socket(getThis(), obj TSRMLS_CC
)) {
718 throw_exce(EX_CONNECTION_FAILED TSRMLS_CC
, "Connection failed (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
724 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset
, 0, 0, 0)
726 static PHP_METHOD(pqconn
, reset
) {
727 zend_error_handling zeh
;
730 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
731 rv
= zend_parse_parameters_none();
732 zend_restore_error_handling(&zeh TSRMLS_CC
);
735 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
738 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
740 PQreset(obj
->intern
->conn
);
742 if (CONNECTION_OK
!= PQstatus(obj
->intern
->conn
)) {
743 throw_exce(EX_CONNECTION_FAILED TSRMLS_CC
, "Connection reset failed: (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
746 php_pqconn_notify_listeners(obj TSRMLS_CC
);
751 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset_async
, 0, 0, 0)
753 static PHP_METHOD(pqconn
, resetAsync
) {
754 zend_error_handling zeh
;
757 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
758 rv
= zend_parse_parameters_none();
759 zend_restore_error_handling(&zeh TSRMLS_CC
);
762 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
765 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
767 if (!PQresetStart(obj
->intern
->conn
)) {
768 throw_exce(EX_IO TSRMLS_CC
, "Failed to start connection reset (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
770 obj
->intern
->poller
= (int (*)(PGconn
*)) PQresetPoll
;
773 php_pqconn_notify_listeners(obj TSRMLS_CC
);
778 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unlisten
, 0, 0, 1)
779 ZEND_ARG_INFO(0, channel
)
781 static PHP_METHOD(pqconn
, unlisten
)
783 zend_error_handling zeh
;
788 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
789 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &channel_str
, &channel_len
);
790 zend_restore_error_handling(&zeh TSRMLS_CC
);
793 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
796 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
797 } else if (SUCCESS
== zend_hash_del(&obj
->intern
->listeners
, channel_str
, channel_len
+ 1)) {
798 PGresult
*res
= unlisten(obj
->intern
->conn
, channel_str
, channel_len TSRMLS_CC
);
801 php_pqres_success(res TSRMLS_CC
);
802 php_pqres_clear(res
);
808 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unlisten_async
, 0, 0, 1)
809 ZEND_ARG_INFO(0, channel
)
811 static PHP_METHOD(pqconn
, unlistenAsync
) {
812 zend_error_handling zeh
;
817 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
818 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &channel_str
, &channel_len
);
819 zend_restore_error_handling(&zeh TSRMLS_CC
);
822 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
825 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
827 char *quoted_channel
= PQescapeIdentifier(obj
->intern
->conn
, channel_str
, channel_len
);
829 if (!quoted_channel
) {
830 throw_exce(EX_ESCAPE TSRMLS_CC
, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
834 smart_str_appends(&cmd
, "UNLISTEN ");
835 smart_str_appends(&cmd
, quoted_channel
);
838 if (!PQsendQuery(obj
->intern
->conn
, cmd
.c
)) {
839 throw_exce(EX_IO TSRMLS_CC
, "Failed to uninstall listener (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
841 obj
->intern
->poller
= PQconsumeInput
;
842 zend_hash_del(&obj
->intern
->listeners
, channel_str
, channel_len
+ 1);
845 smart_str_free(&cmd
);
846 PQfreemem(quoted_channel
);
847 php_pqconn_notify_listeners(obj TSRMLS_CC
);
853 static void php_pqconn_add_listener(php_pqconn_object_t
*obj
, const char *channel_str
, size_t channel_len
, php_pq_callback_t
*listener TSRMLS_DC
)
855 HashTable ht
, *existing_listeners
;
857 php_pq_callback_addref(listener
);
859 if (SUCCESS
== zend_hash_find(&obj
->intern
->listeners
, channel_str
, channel_len
+ 1, (void *) &existing_listeners
)) {
860 zend_hash_next_index_insert(existing_listeners
, (void *) listener
, sizeof(*listener
), NULL
);
862 zend_hash_init(&ht
, 1, NULL
, (dtor_func_t
) php_pq_callback_dtor
, 0);
863 zend_hash_next_index_insert(&ht
, (void *) listener
, sizeof(*listener
), NULL
);
864 zend_hash_add(&obj
->intern
->listeners
, channel_str
, channel_len
+ 1, (void *) &ht
, sizeof(HashTable
), NULL
);
868 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen
, 0, 0, 2)
869 ZEND_ARG_INFO(0, channel
)
870 ZEND_ARG_INFO(0, callable
)
872 static PHP_METHOD(pqconn
, listen
) {
873 zend_error_handling zeh
;
874 char *channel_str
= NULL
;
876 php_pq_callback_t listener
= {{0}};
879 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
880 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sf", &channel_str
, &channel_len
, &listener
.fci
, &listener
.fcc
);
881 zend_restore_error_handling(&zeh TSRMLS_CC
);
884 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
887 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
889 char *quoted_channel
= PQescapeIdentifier(obj
->intern
->conn
, channel_str
, channel_len
);
891 if (!quoted_channel
) {
892 throw_exce(EX_ESCAPE TSRMLS_CC
, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
897 smart_str_appends(&cmd
, "LISTEN ");
898 smart_str_appends(&cmd
, quoted_channel
);
901 res
= php_pq_exec(obj
->intern
->conn
, cmd
.c
);
903 smart_str_free(&cmd
);
904 PQfreemem(quoted_channel
);
907 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to install listener (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
909 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
910 obj
->intern
->poller
= PQconsumeInput
;
911 php_pqconn_add_listener(obj
, channel_str
, channel_len
, &listener TSRMLS_CC
);
913 php_pqres_clear(res
);
916 php_pqconn_notify_listeners(obj TSRMLS_CC
);
922 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen_async
, 0, 0, 0)
923 ZEND_ARG_INFO(0, channel
)
924 ZEND_ARG_INFO(0, callable
)
926 static PHP_METHOD(pqconn
, listenAsync
) {
927 zend_error_handling zeh
;
928 char *channel_str
= NULL
;
930 php_pq_callback_t listener
= {{0}};
933 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
934 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sf", &channel_str
, &channel_len
, &listener
.fci
, &listener
.fcc
);
935 zend_restore_error_handling(&zeh TSRMLS_CC
);
938 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
941 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
943 char *quoted_channel
= PQescapeIdentifier(obj
->intern
->conn
, channel_str
, channel_len
);
945 if (!quoted_channel
) {
946 throw_exce(EX_ESCAPE TSRMLS_CC
, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
950 smart_str_appends(&cmd
, "LISTEN ");
951 smart_str_appends(&cmd
, quoted_channel
);
954 if (!PQsendQuery(obj
->intern
->conn
, cmd
.c
)) {
955 throw_exce(EX_IO TSRMLS_CC
, "Failed to install listener (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
957 obj
->intern
->poller
= PQconsumeInput
;
958 php_pqconn_add_listener(obj
, channel_str
, channel_len
, &listener TSRMLS_CC
);
961 smart_str_free(&cmd
);
962 PQfreemem(quoted_channel
);
963 php_pqconn_notify_listeners(obj TSRMLS_CC
);
969 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify
, 0, 0, 2)
970 ZEND_ARG_INFO(0, channel
)
971 ZEND_ARG_INFO(0, message
)
973 static PHP_METHOD(pqconn
, notify
) {
974 zend_error_handling zeh
;
975 char *channel_str
, *message_str
;
976 int channel_len
, message_len
;
979 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
980 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss", &channel_str
, &channel_len
, &message_str
, &message_len
);
981 zend_restore_error_handling(&zeh TSRMLS_CC
);
984 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
987 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
990 char *params
[2] = {channel_str
, message_str
};
992 res
= PQexecParams(obj
->intern
->conn
, "select pg_notify($1, $2)", 2, NULL
, (const char *const*) params
, NULL
, NULL
, 0);
995 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
997 php_pqres_success(res TSRMLS_CC
);
998 php_pqres_clear(res
);
1001 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1006 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify_async
, 0, 0, 2)
1007 ZEND_ARG_INFO(0, channel
)
1008 ZEND_ARG_INFO(0, message
)
1009 ZEND_END_ARG_INFO();
1010 static PHP_METHOD(pqconn
, notifyAsync
) {
1011 zend_error_handling zeh
;
1012 char *channel_str
, *message_str
;
1013 int channel_len
, message_len
;
1014 ZEND_RESULT_CODE rv
;
1016 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1017 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss", &channel_str
, &channel_len
, &message_str
, &message_len
);
1018 zend_restore_error_handling(&zeh TSRMLS_CC
);
1020 if (SUCCESS
== rv
) {
1021 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1024 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1026 char *params
[2] = {channel_str
, message_str
};
1028 if (!PQsendQueryParams(obj
->intern
->conn
, "select pg_notify($1, $2)", 2, NULL
, (const char *const*) params
, NULL
, NULL
, 0)) {
1029 throw_exce(EX_IO TSRMLS_CC
, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1031 obj
->intern
->poller
= PQconsumeInput
;
1034 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1039 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll
, 0, 0, 0)
1040 ZEND_END_ARG_INFO();
1041 static PHP_METHOD(pqconn
, poll
) {
1042 zend_error_handling zeh
;
1043 ZEND_RESULT_CODE rv
;
1045 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1046 rv
= zend_parse_parameters_none();
1047 zend_restore_error_handling(&zeh TSRMLS_CC
);
1049 if (SUCCESS
== rv
) {
1050 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1053 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1054 } else if (!obj
->intern
->poller
) {
1055 throw_exce(EX_RUNTIME TSRMLS_CC
, "No asynchronous operation active");
1057 if (obj
->intern
->poller
== PQconsumeInput
) {
1058 RETVAL_LONG(obj
->intern
->poller(obj
->intern
->conn
) * PGRES_POLLING_OK
);
1060 RETVAL_LONG(obj
->intern
->poller(obj
->intern
->conn
));
1062 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1067 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_flush
, 0, 0, 0)
1068 ZEND_END_ARG_INFO();
1069 static PHP_METHOD(pqconn
, flush
) {
1070 zend_error_handling zeh
;
1071 ZEND_RESULT_CODE rv
;
1073 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1074 rv
= zend_parse_parameters_none();
1075 zend_restore_error_handling(&zeh TSRMLS_CC
);
1077 if (SUCCESS
== rv
) {
1078 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1081 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1082 } else if (!obj
->intern
->poller
) {
1083 throw_exce(EX_RUNTIME TSRMLS_CC
, "No asynchronous operation active");
1085 switch (PQflush(obj
->intern
->conn
)) {
1088 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to flush connection: %s", PHP_PQerrorMessage(obj
->intern
->conn
));
1101 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec
, 0, 0, 1)
1102 ZEND_ARG_INFO(0, query
)
1103 ZEND_END_ARG_INFO();
1104 static PHP_METHOD(pqconn
, exec
) {
1105 zend_error_handling zeh
;
1108 ZEND_RESULT_CODE rv
;
1110 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1111 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &query_str
, &query_len
);
1112 zend_restore_error_handling(&zeh TSRMLS_CC
);
1114 if (SUCCESS
== rv
) {
1115 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1118 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1120 PGresult
*res
= php_pq_exec(obj
->intern
->conn
, query_str
);
1123 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1124 } else if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1125 php_pq_object_to_zval_no_addref(PQresultInstanceData(res
, php_pqconn_event
), &return_value TSRMLS_CC
);
1127 php_pqres_clear(res
);
1130 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1135 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_get_result
, 0, 0, 0)
1136 ZEND_END_ARG_INFO();
1137 static PHP_METHOD(pqconn
, getResult
) {
1138 zend_error_handling zeh
;
1139 ZEND_RESULT_CODE rv
;
1141 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1142 rv
= zend_parse_parameters_none();
1143 zend_restore_error_handling(&zeh TSRMLS_CC
);
1145 if (SUCCESS
== rv
) {
1146 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1149 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1151 PGresult
*res
= PQgetResult(obj
->intern
->conn
);
1156 php_pq_object_to_zval_no_addref(PQresultInstanceData(res
, php_pqconn_event
), &return_value TSRMLS_CC
);
1159 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1164 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async
, 0, 0, 1)
1165 ZEND_ARG_INFO(0, query
)
1166 ZEND_ARG_INFO(0, callable
)
1167 ZEND_END_ARG_INFO();
1168 static PHP_METHOD(pqconn
, execAsync
) {
1169 zend_error_handling zeh
;
1170 php_pq_callback_t resolver
= {{0}};
1173 ZEND_RESULT_CODE rv
;
1175 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1176 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|f", &query_str
, &query_len
, &resolver
.fci
, &resolver
.fcc
);
1177 zend_restore_error_handling(&zeh TSRMLS_CC
);
1179 if (SUCCESS
== rv
) {
1180 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1183 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1184 } else if (!PQsendQuery(obj
->intern
->conn
, query_str
)) {
1185 throw_exce(EX_IO TSRMLS_CC
, "Failed to execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1186 #if HAVE_PQSETSINGLEROWMODE
1187 } else if (obj
->intern
->unbuffered
&& !PQsetSingleRowMode(obj
->intern
->conn
)) {
1188 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1191 php_pq_callback_recurse(&obj
->intern
->onevent
, &resolver TSRMLS_CC
);
1192 obj
->intern
->poller
= PQconsumeInput
;
1193 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1198 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params
, 0, 0, 2)
1199 ZEND_ARG_INFO(0, query
)
1200 ZEND_ARG_ARRAY_INFO(0, params
, 0)
1201 ZEND_ARG_ARRAY_INFO(0, types
, 1)
1202 ZEND_END_ARG_INFO();
1203 static PHP_METHOD(pqconn
, execParams
) {
1204 zend_error_handling zeh
;
1208 zval
*ztypes
= NULL
;
1209 ZEND_RESULT_CODE rv
;
1211 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1212 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sa/|a/!", &query_str
, &query_len
, &zparams
, &ztypes
);
1213 zend_restore_error_handling(&zeh TSRMLS_CC
);
1215 if (SUCCESS
== rv
) {
1216 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1219 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1222 php_pq_params_t
*params
;
1224 params
= php_pq_params_init(&obj
->intern
->converters
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL
, Z_ARRVAL_P(zparams
) TSRMLS_CC
);
1225 res
= PQexecParams(obj
->intern
->conn
, query_str
, params
->param
.count
, params
->type
.oids
, (const char *const*) params
->param
.strings
, NULL
, NULL
, 0);
1226 php_pq_params_free(¶ms
);
1229 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1231 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1232 php_pq_object_to_zval_no_addref(PQresultInstanceData(res
, php_pqconn_event
), &return_value TSRMLS_CC
);
1234 php_pqres_clear(res
);
1237 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1243 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async
, 0, 0, 2)
1244 ZEND_ARG_INFO(0, query
)
1245 ZEND_ARG_ARRAY_INFO(0, params
, 0)
1246 ZEND_ARG_ARRAY_INFO(0, types
, 1)
1247 ZEND_ARG_INFO(0, callable
)
1248 ZEND_END_ARG_INFO();
1249 static PHP_METHOD(pqconn
, execParamsAsync
) {
1250 zend_error_handling zeh
;
1251 php_pq_callback_t resolver
= {{0}};
1255 zval
*ztypes
= NULL
;
1256 ZEND_RESULT_CODE rv
;
1258 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1259 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sa/|a/!f", &query_str
, &query_len
, &zparams
, &ztypes
, &resolver
.fci
, &resolver
.fcc
);
1260 zend_restore_error_handling(&zeh TSRMLS_CC
);
1262 if (SUCCESS
== rv
) {
1263 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1266 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1269 php_pq_params_t
*params
;
1271 params
= php_pq_params_init(&obj
->intern
->converters
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL
, Z_ARRVAL_P(zparams
) TSRMLS_CC
);
1272 rc
= PQsendQueryParams(obj
->intern
->conn
, query_str
, params
->param
.count
, params
->type
.oids
, (const char *const*) params
->param
.strings
, NULL
, NULL
, 0);
1273 php_pq_params_free(¶ms
);
1276 throw_exce(EX_IO TSRMLS_CC
, "Failed to execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1277 #if HAVE_PQSETSINGLEROWMODE
1278 } else if (obj
->intern
->unbuffered
&& !PQsetSingleRowMode(obj
->intern
->conn
)) {
1279 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1282 php_pq_callback_recurse(&obj
->intern
->onevent
, &resolver TSRMLS_CC
);
1283 obj
->intern
->poller
= PQconsumeInput
;
1284 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1288 zend_restore_error_handling(&zeh TSRMLS_CC
);
1291 ZEND_RESULT_CODE
php_pqconn_prepare(zval
*object
, php_pqconn_object_t
*obj
, const char *name
, const char *query
, php_pq_params_t
*params TSRMLS_DC
)
1294 ZEND_RESULT_CODE rv
;
1297 obj
= zend_object_store_get_object(object TSRMLS_CC
);
1300 res
= php_pq_prepare(obj
->intern
->conn
, name
, query
, params
->type
.count
, params
->type
.oids
);
1304 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1306 rv
= php_pqres_success(res TSRMLS_CC
);
1307 php_pqres_clear(res
);
1308 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1314 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare
, 0, 0, 2)
1315 ZEND_ARG_INFO(0, name
)
1316 ZEND_ARG_INFO(0, query
)
1317 ZEND_ARG_ARRAY_INFO(0, types
, 1)
1318 ZEND_END_ARG_INFO();
1319 static PHP_METHOD(pqconn
, prepare
) {
1320 zend_error_handling zeh
;
1321 zval
*ztypes
= NULL
;
1322 char *name_str
, *query_str
;
1323 int name_len
, *query_len
;
1324 ZEND_RESULT_CODE rv
;
1326 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1327 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|a/!", &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
);
1328 zend_restore_error_handling(&zeh TSRMLS_CC
);
1330 if (SUCCESS
== rv
) {
1331 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1334 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1336 php_pq_params_t
*params
= php_pq_params_init(&obj
->intern
->converters
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL
, NULL TSRMLS_CC
);
1338 if (SUCCESS
!= php_pqconn_prepare(getThis(), obj
, name_str
, query_str
, params TSRMLS_CC
)) {
1339 php_pq_params_free(¶ms
);
1341 php_pqstm_t
*stm
= php_pqstm_init(obj
, name_str
, query_str
, params TSRMLS_CC
);
1343 return_value
->type
= IS_OBJECT
;
1344 return_value
->value
.obj
= php_pqstm_create_object_ex(php_pqstm_class_entry
, stm
, NULL TSRMLS_CC
);
1350 ZEND_RESULT_CODE
php_pqconn_prepare_async(zval
*object
, php_pqconn_object_t
*obj
, const char *name
, const char *query
, php_pq_params_t
*params TSRMLS_DC
)
1352 ZEND_RESULT_CODE rv
;
1355 obj
= zend_object_store_get_object(object TSRMLS_CC
);
1358 if (!PQsendPrepare(obj
->intern
->conn
, name
, query
, params
->type
.count
, params
->type
.oids
)) {
1360 throw_exce(EX_IO TSRMLS_CC
, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1363 obj
->intern
->poller
= PQconsumeInput
;
1364 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1370 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async
, 0, 0, 2)
1371 ZEND_ARG_INFO(0, name
)
1372 ZEND_ARG_INFO(0, query
)
1373 ZEND_ARG_ARRAY_INFO(0, types
, 1)
1374 ZEND_END_ARG_INFO();
1375 static PHP_METHOD(pqconn
, prepareAsync
) {
1376 zend_error_handling zeh
;
1377 zval
*ztypes
= NULL
;
1378 char *name_str
, *query_str
;
1379 int name_len
, *query_len
;
1380 ZEND_RESULT_CODE rv
;
1382 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1383 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|a/!", &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
);
1384 zend_restore_error_handling(&zeh TSRMLS_CC
);
1386 if (SUCCESS
== rv
) {
1387 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1390 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1392 php_pq_params_t
*params
= php_pq_params_init(&obj
->intern
->converters
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL
, NULL TSRMLS_CC
);
1394 if (SUCCESS
!= php_pqconn_prepare_async(getThis(), obj
, name_str
, query_str
, params TSRMLS_CC
)) {
1395 php_pq_params_free(¶ms
);
1397 php_pqstm_t
*stm
= php_pqstm_init(obj
, name_str
, query_str
, params TSRMLS_CC
);
1399 return_value
->type
= IS_OBJECT
;
1400 return_value
->value
.obj
= php_pqstm_create_object_ex(php_pqstm_class_entry
, stm
, NULL TSRMLS_CC
);
1406 ZEND_RESULT_CODE
php_pqconn_declare(zval
*object
, php_pqconn_object_t
*obj
, const char *decl TSRMLS_DC
)
1409 ZEND_RESULT_CODE rv
;
1412 obj
= zend_object_store_get_object(object TSRMLS_CC
);
1415 res
= php_pq_exec(obj
->intern
->conn
, decl
);
1419 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1421 rv
= php_pqres_success(res TSRMLS_CC
);
1422 php_pqres_clear(res
);
1423 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1429 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare
, 0, 0, 3)
1430 ZEND_ARG_INFO(0, name
)
1431 ZEND_ARG_INFO(0, flags
)
1432 ZEND_ARG_INFO(0, query
)
1433 ZEND_END_ARG_INFO();
1434 static PHP_METHOD(pqconn
, declare
) {
1435 zend_error_handling zeh
;
1436 char *name_str
, *query_str
;
1437 int name_len
, query_len
;
1439 ZEND_RESULT_CODE rv
;
1441 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1442 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sls", &name_str
, &name_len
, &flags
, &query_str
, &query_len
);
1443 zend_restore_error_handling(&zeh TSRMLS_CC
);
1445 if (SUCCESS
== rv
) {
1446 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1449 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1452 char *decl
= php_pqcur_declare_str(name_str
, name_len
, flags
, query_str
, query_len
, &query_offset
);
1454 if (SUCCESS
!= php_pqconn_declare(getThis(), obj
, decl TSRMLS_CC
)) {
1457 php_pqcur_t
*cur
= php_pqcur_init(obj
, name_str
, decl
, query_offset
, flags TSRMLS_CC
);
1459 return_value
->type
= IS_OBJECT
;
1460 return_value
->value
.obj
= php_pqcur_create_object_ex(php_pqcur_class_entry
, cur
, NULL TSRMLS_CC
);
1466 ZEND_RESULT_CODE
php_pqconn_declare_async(zval
*object
, php_pqconn_object_t
*obj
, const char *decl TSRMLS_DC
)
1468 ZEND_RESULT_CODE rv
;
1471 obj
= zend_object_store_get_object(object TSRMLS_CC
);
1474 if (!PQsendQuery(obj
->intern
->conn
, decl
)) {
1476 throw_exce(EX_IO TSRMLS_CC
, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1479 obj
->intern
->poller
= PQconsumeInput
;
1480 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1486 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_declare_async
, 0, 0, 2)
1487 ZEND_ARG_INFO(0, name
)
1488 ZEND_ARG_INFO(0, flags
)
1489 ZEND_ARG_INFO(0, query
)
1490 ZEND_END_ARG_INFO();
1491 static PHP_METHOD(pqconn
, declareAsync
) {
1492 zend_error_handling zeh
;
1493 char *name_str
, *query_str
;
1494 int name_len
, query_len
;
1496 ZEND_RESULT_CODE rv
;
1498 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1499 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sls", &name_str
, &name_len
, &flags
, &query_str
, &query_len
);
1500 zend_restore_error_handling(&zeh TSRMLS_CC
);
1502 if (SUCCESS
== rv
) {
1503 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1506 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1509 char *decl
= php_pqcur_declare_str(name_str
, name_len
, flags
, query_str
, query_len
, &query_offset
);
1511 if (SUCCESS
!= php_pqconn_declare_async(getThis(), obj
, decl TSRMLS_CC
)) {
1514 php_pqcur_t
*cur
= php_pqcur_init(obj
, name_str
, decl
, query_offset
, flags TSRMLS_CC
);
1516 return_value
->type
= IS_OBJECT
;
1517 return_value
->value
.obj
= php_pqcur_create_object_ex(php_pqcur_class_entry
, cur
, NULL TSRMLS_CC
);
1523 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote
, 0, 0, 1)
1524 ZEND_ARG_INFO(0, string
)
1525 ZEND_END_ARG_INFO();
1526 static PHP_METHOD(pqconn
, quote
) {
1530 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
1531 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1534 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1536 char *quoted
= PQescapeLiteral(obj
->intern
->conn
, str
, len
);
1539 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to quote string (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1542 RETVAL_STRING(quoted
, 1);
1549 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name
, 0, 0, 1)
1550 ZEND_ARG_INFO(0, type
)
1551 ZEND_END_ARG_INFO();
1552 static PHP_METHOD(pqconn
, quoteName
) {
1556 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
1557 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1560 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1562 char *quoted
= PQescapeIdentifier(obj
->intern
->conn
, str
, len
);
1565 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to quote name (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1568 RETVAL_STRING(quoted
, 1);
1575 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea
, 0, 0, 1)
1576 ZEND_ARG_INFO(0, bytea
)
1577 ZEND_END_ARG_INFO();
1578 static PHP_METHOD(pqconn
, escapeBytea
) {
1582 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
1583 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1586 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1589 char *escaped_str
= (char *) PQescapeByteaConn(obj
->intern
->conn
, (unsigned char *) str
, len
, &escaped_len
);
1592 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to escape bytea (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1595 RETVAL_STRINGL(escaped_str
, escaped_len
- 1, 1);
1596 PQfreemem(escaped_str
);
1602 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea
, 0, 0, 1)
1603 ZEND_ARG_INFO(0, bytea
)
1604 ZEND_END_ARG_INFO();
1605 static PHP_METHOD(pqconn
, unescapeBytea
) {
1609 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
1610 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1613 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1615 size_t unescaped_len
;
1616 char *unescaped_str
= (char *) PQunescapeBytea((unsigned char *)str
, &unescaped_len
);
1618 if (!unescaped_str
) {
1619 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to unescape bytea (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1622 RETVAL_STRINGL(unescaped_str
, unescaped_len
, 1);
1623 PQfreemem(unescaped_str
);
1629 ZEND_RESULT_CODE
php_pqconn_start_transaction(zval
*zconn
, php_pqconn_object_t
*conn_obj
, long isolation
, zend_bool readonly
, zend_bool deferrable TSRMLS_DC
)
1631 ZEND_RESULT_CODE rv
= FAILURE
;
1634 conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
1637 if (!conn_obj
->intern
) {
1638 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1641 smart_str cmd
= {0};
1642 const char *il
= php_pq_isolation_level(&isolation
);
1644 smart_str_appends(&cmd
, "START TRANSACTION ISOLATION LEVEL ");
1645 smart_str_appends(&cmd
, il
);
1646 smart_str_appends(&cmd
, ", READ ");
1647 smart_str_appends(&cmd
, readonly
? "ONLY" : "WRITE");
1648 smart_str_appends(&cmd
, ",");
1649 smart_str_appends(&cmd
, deferrable
? "" : " NOT");
1650 smart_str_appends(&cmd
, " DEFERRABLE");
1653 res
= php_pq_exec(conn_obj
->intern
->conn
, cmd
.c
);
1656 throw_exce(EX_RUNTIME TSRMLS_CC
, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj
->intern
->conn
));
1658 rv
= php_pqres_success(res TSRMLS_CC
);
1659 php_pqres_clear(res
);
1660 php_pqconn_notify_listeners(conn_obj TSRMLS_CC
);
1663 smart_str_free(&cmd
);
1669 ZEND_RESULT_CODE
php_pqconn_start_transaction_async(zval
*zconn
, php_pqconn_object_t
*conn_obj
, long isolation
, zend_bool readonly
, zend_bool deferrable TSRMLS_DC
)
1671 ZEND_RESULT_CODE rv
= FAILURE
;
1674 conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
1677 if (!conn_obj
->intern
) {
1678 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1680 smart_str cmd
= {0};
1681 const char *il
= php_pq_isolation_level(&isolation
);
1683 smart_str_appends(&cmd
, "START TRANSACTION ISOLATION LEVEL ");
1684 smart_str_appends(&cmd
, il
);
1685 smart_str_appends(&cmd
, ", READ ");
1686 smart_str_appends(&cmd
, readonly
? "ONLY" : "WRITE");
1687 smart_str_appends(&cmd
, ",");
1688 smart_str_appends(&cmd
, deferrable
? "" : "NOT ");
1689 smart_str_appends(&cmd
, " DEFERRABLE");
1692 if (!PQsendQuery(conn_obj
->intern
->conn
, cmd
.c
)) {
1693 throw_exce(EX_IO TSRMLS_CC
, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj
->intern
->conn
));
1696 conn_obj
->intern
->poller
= PQconsumeInput
;
1697 php_pqconn_notify_listeners(conn_obj TSRMLS_CC
);
1700 smart_str_free(&cmd
);
1706 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction
, 0, 0, 0)
1707 ZEND_ARG_INFO(0, isolation
)
1708 ZEND_ARG_INFO(0, readonly
)
1709 ZEND_ARG_INFO(0, deferrable
)
1710 ZEND_END_ARG_INFO();
1711 static PHP_METHOD(pqconn
, startTransaction
) {
1712 zend_error_handling zeh
;
1713 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1714 long isolation
= obj
->intern
? obj
->intern
->default_txn_isolation
: PHP_PQTXN_READ_COMMITTED
;
1715 zend_bool readonly
= obj
->intern
? obj
->intern
->default_txn_readonly
: 0;
1716 zend_bool deferrable
= obj
->intern
? obj
->intern
->default_txn_deferrable
: 0;
1717 ZEND_RESULT_CODE rv
;
1719 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1720 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|lbb", &isolation
, &readonly
, &deferrable
);
1721 zend_restore_error_handling(&zeh TSRMLS_CC
);
1723 if (SUCCESS
== rv
) {
1724 rv
= php_pqconn_start_transaction(getThis(), obj
, isolation
, readonly
, deferrable TSRMLS_CC
);
1726 if (SUCCESS
== rv
) {
1727 php_pqtxn_t
*txn
= ecalloc(1, sizeof(*txn
));
1729 php_pq_object_addref(obj TSRMLS_CC
);
1732 txn
->isolation
= isolation
;
1733 txn
->readonly
= readonly
;
1734 txn
->deferrable
= deferrable
;
1736 return_value
->type
= IS_OBJECT
;
1737 return_value
->value
.obj
= php_pqtxn_create_object_ex(php_pqtxn_class_entry
, txn
, NULL TSRMLS_CC
);
1742 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async
, 0, 0, 0)
1743 ZEND_ARG_INFO(0, isolation
)
1744 ZEND_ARG_INFO(0, readonly
)
1745 ZEND_ARG_INFO(0, deferrable
)
1746 ZEND_END_ARG_INFO();
1747 static PHP_METHOD(pqconn
, startTransactionAsync
) {
1748 zend_error_handling zeh
;
1749 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1750 long isolation
= obj
->intern
? obj
->intern
->default_txn_isolation
: PHP_PQTXN_READ_COMMITTED
;
1751 zend_bool readonly
= obj
->intern
? obj
->intern
->default_txn_readonly
: 0;
1752 zend_bool deferrable
= obj
->intern
? obj
->intern
->default_txn_deferrable
: 0;
1753 ZEND_RESULT_CODE rv
;
1755 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1756 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|lbb", &isolation
, &readonly
, &deferrable
);
1757 zend_restore_error_handling(&zeh TSRMLS_CC
);
1759 if (SUCCESS
== rv
) {
1760 rv
= php_pqconn_start_transaction_async(getThis(), obj
, isolation
, readonly
, deferrable TSRMLS_CC
);
1762 if (SUCCESS
== rv
) {
1763 php_pqtxn_t
*txn
= ecalloc(1, sizeof(*txn
));
1765 php_pq_object_addref(obj TSRMLS_CC
);
1768 txn
->isolation
= isolation
;
1769 txn
->readonly
= readonly
;
1770 txn
->deferrable
= deferrable
;
1772 return_value
->type
= IS_OBJECT
;
1773 return_value
->value
.obj
= php_pqtxn_create_object_ex(php_pqtxn_class_entry
, txn
, NULL TSRMLS_CC
);
1778 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace
, 0, 0, 0)
1779 ZEND_ARG_INFO(0, stdio_stream
)
1780 ZEND_END_ARG_INFO();
1781 static PHP_METHOD(pqconn
, trace
) {
1782 zval
*zstream
= NULL
;
1784 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|r!", &zstream
)) {
1785 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1788 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1791 PQuntrace(obj
->intern
->conn
);
1795 php_stream
*stream
= NULL
;
1797 php_stream_from_zval(stream
, &zstream
);
1799 if (SUCCESS
!= php_stream_cast(stream
, PHP_STREAM_AS_STDIO
, (void *) &fp
, REPORT_ERRORS
)) {
1802 stream
->flags
|= PHP_STREAM_FLAG_NO_CLOSE
;
1803 PQtrace(obj
->intern
->conn
, fp
);
1811 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_off
, 0, 0, 1)
1812 ZEND_ARG_INFO(0, type
)
1813 ZEND_END_ARG_INFO();
1814 static PHP_METHOD(pqconn
, off
) {
1815 zend_error_handling zeh
;
1818 ZEND_RESULT_CODE rv
;
1820 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1821 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &type_str
, &type_len
);
1822 zend_restore_error_handling(&zeh TSRMLS_CC
);
1824 if (SUCCESS
== rv
) {
1825 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1828 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1830 RETURN_BOOL(SUCCESS
== zend_hash_del(&obj
->intern
->eventhandlers
, type_str
, type_len
+ 1));
1835 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_on
, 0, 0, 2)
1836 ZEND_ARG_INFO(0, type
)
1837 ZEND_ARG_INFO(0, callable
)
1838 ZEND_END_ARG_INFO();
1839 static PHP_METHOD(pqconn
, on
) {
1840 zend_error_handling zeh
;
1843 php_pq_callback_t cb
= {{0}};
1844 ZEND_RESULT_CODE rv
;
1846 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1847 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sf", &type_str
, &type_len
, &cb
.fci
, &cb
.fcc
);
1848 zend_restore_error_handling(&zeh TSRMLS_CC
);
1850 if (SUCCESS
== rv
) {
1851 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1854 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1856 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1858 RETVAL_LONG(php_pqconn_add_eventhandler(obj
, type_str
, type_len
, &cb TSRMLS_CC
));
1863 struct apply_set_converter_arg
{
1869 static int apply_set_converter(void *p
, void *a TSRMLS_DC
)
1871 zval
*tmp
, **zoid
= p
;
1872 struct apply_set_converter_arg
*arg
= a
;
1876 convert_to_long_ex(&tmp
);
1878 Z_ADDREF_PP(arg
->zconv
);
1879 zend_hash_index_update(arg
->ht
, Z_LVAL_P(tmp
), arg
->zconv
, sizeof(zval
*), NULL
);
1881 zend_hash_index_del(arg
->ht
, Z_LVAL_P(tmp
));
1883 zval_ptr_dtor(&tmp
);
1885 return ZEND_HASH_APPLY_KEEP
;
1888 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_set_converter
, 0, 0, 1)
1889 ZEND_ARG_OBJ_INFO(0, converter
, pq
\\Converter
, 0)
1890 ZEND_END_ARG_INFO();
1891 static PHP_METHOD(pqconn
, setConverter
) {
1892 ZEND_RESULT_CODE rv
;
1893 zend_error_handling zeh
;
1896 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1897 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &zcnv
, php_pqconv_class_entry
);
1898 zend_restore_error_handling(&zeh TSRMLS_CC
);
1900 if (SUCCESS
== rv
) {
1901 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1904 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1906 zval
*tmp
, *zoids
= NULL
;
1907 struct apply_set_converter_arg arg
= {NULL
};
1909 zend_call_method_with_0_params(&zcnv
, NULL
, NULL
, "converttypes", &zoids
);
1912 convert_to_array_ex(&tmp
);
1914 arg
.ht
= &obj
->intern
->converters
;
1918 zend_hash_apply_with_argument(Z_ARRVAL_P(tmp
), apply_set_converter
, &arg TSRMLS_CC
);
1920 zval_ptr_dtor(&tmp
);
1921 zval_ptr_dtor(&zoids
);
1926 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unset_converter
, 0, 0, 1)
1927 ZEND_ARG_OBJ_INFO(0, converter
, pq
\\Converter
, 0)
1928 ZEND_END_ARG_INFO();
1929 static PHP_METHOD(pqconn
, unsetConverter
) {
1930 ZEND_RESULT_CODE rv
;
1931 zend_error_handling zeh
;
1934 zend_replace_error_handling(EH_THROW
, exce(EX_INVALID_ARGUMENT
), &zeh TSRMLS_CC
);
1935 rv
= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &zcnv
, php_pqconv_class_entry
);
1936 zend_restore_error_handling(&zeh TSRMLS_CC
);
1938 if (SUCCESS
== rv
) {
1939 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1942 throw_exce(EX_UNINITIALIZED TSRMLS_CC
, "pq\\Connection not initialized");
1944 zval
*tmp
, *zoids
= NULL
;
1945 struct apply_set_converter_arg arg
= {NULL
};
1947 zend_call_method_with_0_params(&zcnv
, NULL
, NULL
, "converttypes", &zoids
);
1950 convert_to_array_ex(&tmp
);
1952 arg
.ht
= &obj
->intern
->converters
;
1956 zend_hash_apply_with_argument(Z_ARRVAL_P(tmp
), apply_set_converter
, &arg TSRMLS_CC
);
1958 zval_ptr_dtor(&tmp
);
1959 zval_ptr_dtor(&zoids
);
1964 static zend_function_entry php_pqconn_methods
[] = {
1965 PHP_ME(pqconn
, __construct
, ai_pqconn_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
1966 PHP_ME(pqconn
, reset
, ai_pqconn_reset
, ZEND_ACC_PUBLIC
)
1967 PHP_ME(pqconn
, resetAsync
, ai_pqconn_reset_async
, ZEND_ACC_PUBLIC
)
1968 PHP_ME(pqconn
, poll
, ai_pqconn_poll
, ZEND_ACC_PUBLIC
)
1969 PHP_ME(pqconn
, flush
, ai_pqconn_flush
, ZEND_ACC_PUBLIC
)
1970 PHP_ME(pqconn
, exec
, ai_pqconn_exec
, ZEND_ACC_PUBLIC
)
1971 PHP_ME(pqconn
, execAsync
, ai_pqconn_exec_async
, ZEND_ACC_PUBLIC
)
1972 PHP_ME(pqconn
, execParams
, ai_pqconn_exec_params
, ZEND_ACC_PUBLIC
)
1973 PHP_ME(pqconn
, execParamsAsync
, ai_pqconn_exec_params_async
, ZEND_ACC_PUBLIC
)
1974 PHP_ME(pqconn
, prepare
, ai_pqconn_prepare
, ZEND_ACC_PUBLIC
)
1975 PHP_ME(pqconn
, prepareAsync
, ai_pqconn_prepare_async
, ZEND_ACC_PUBLIC
)
1976 PHP_ME(pqconn
, declare
, ai_pqconn_declare
, ZEND_ACC_PUBLIC
)
1977 PHP_ME(pqconn
, declareAsync
, ai_pqconn_declare_async
, ZEND_ACC_PUBLIC
)
1978 PHP_ME(pqconn
, unlisten
, ai_pqconn_unlisten
, ZEND_ACC_PUBLIC
)
1979 PHP_ME(pqconn
, unlistenAsync
, ai_pqconn_unlisten_async
, ZEND_ACC_PUBLIC
)
1980 PHP_ME(pqconn
, listen
, ai_pqconn_listen
, ZEND_ACC_PUBLIC
)
1981 PHP_ME(pqconn
, listenAsync
, ai_pqconn_listen_async
, ZEND_ACC_PUBLIC
)
1982 PHP_ME(pqconn
, notify
, ai_pqconn_notify
, ZEND_ACC_PUBLIC
)
1983 PHP_ME(pqconn
, notifyAsync
, ai_pqconn_notify_async
, ZEND_ACC_PUBLIC
)
1984 PHP_ME(pqconn
, getResult
, ai_pqconn_get_result
, ZEND_ACC_PUBLIC
)
1985 PHP_ME(pqconn
, quote
, ai_pqconn_quote
, ZEND_ACC_PUBLIC
)
1986 PHP_ME(pqconn
, quoteName
, ai_pqconn_quote_name
, ZEND_ACC_PUBLIC
)
1987 PHP_ME(pqconn
, escapeBytea
, ai_pqconn_escape_bytea
, ZEND_ACC_PUBLIC
)
1988 PHP_ME(pqconn
, unescapeBytea
, ai_pqconn_unescape_bytea
, ZEND_ACC_PUBLIC
)
1989 PHP_ME(pqconn
, startTransaction
, ai_pqconn_start_transaction
, ZEND_ACC_PUBLIC
)
1990 PHP_ME(pqconn
, startTransactionAsync
, ai_pqconn_start_transaction_async
, ZEND_ACC_PUBLIC
)
1991 PHP_ME(pqconn
, trace
, ai_pqconn_trace
, ZEND_ACC_PUBLIC
)
1992 PHP_ME(pqconn
, off
, ai_pqconn_off
, ZEND_ACC_PUBLIC
)
1993 PHP_ME(pqconn
, on
, ai_pqconn_on
, ZEND_ACC_PUBLIC
)
1994 PHP_ME(pqconn
, setConverter
, ai_pqconn_set_converter
, ZEND_ACC_PUBLIC
)
1995 PHP_ME(pqconn
, unsetConverter
, ai_pqconn_unset_converter
, ZEND_ACC_PUBLIC
)
1999 PHP_MSHUTDOWN_FUNCTION(pqconn
)
2001 zend_hash_destroy(&php_pqconn_object_prophandlers
);
2005 PHP_MINIT_FUNCTION(pqconn
)
2007 zend_class_entry ce
= {0};
2008 php_pq_object_prophandler_t ph
= {0};
2010 INIT_NS_CLASS_ENTRY(ce
, "pq", "Connection", php_pqconn_methods
);
2011 php_pqconn_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
2012 php_pqconn_class_entry
->create_object
= php_pqconn_create_object
;
2014 memcpy(&php_pqconn_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
2015 php_pqconn_object_handlers
.read_property
= php_pq_object_read_prop
;
2016 php_pqconn_object_handlers
.write_property
= php_pq_object_write_prop
;
2017 php_pqconn_object_handlers
.clone_obj
= NULL
;
2018 php_pqconn_object_handlers
.get_property_ptr_ptr
= NULL
;
2019 php_pqconn_object_handlers
.get_gc
= NULL
;
2020 php_pqconn_object_handlers
.get_properties
= php_pq_object_properties
;
2021 php_pqconn_object_handlers
.get_debug_info
= php_pq_object_debug_info
;
2023 zend_hash_init(&php_pqconn_object_prophandlers
, 21, NULL
, NULL
, 1);
2025 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("status"), CONNECTION_BAD
, ZEND_ACC_PUBLIC TSRMLS_CC
);
2026 ph
.read
= php_pqconn_object_read_status
;
2027 zend_hash_add(&php_pqconn_object_prophandlers
, "status", sizeof("status"), (void *) &ph
, sizeof(ph
), NULL
);
2029 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN
, ZEND_ACC_PUBLIC TSRMLS_CC
);
2030 ph
.read
= php_pqconn_object_read_transaction_status
;
2031 zend_hash_add(&php_pqconn_object_prophandlers
, "transactionStatus", sizeof("transactionStatus"), (void *) &ph
, sizeof(ph
), NULL
);
2033 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2034 ph
.read
= NULL
; /* forward to std prophandler */
2035 zend_hash_add(&php_pqconn_object_prophandlers
, "socket", sizeof("socket"), (void *) &ph
, sizeof(ph
), NULL
);
2037 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2038 ph
.read
= php_pqconn_object_read_error_message
;
2039 zend_hash_add(&php_pqconn_object_prophandlers
, "errorMessage", sizeof("errorMessage"), (void *) &ph
, sizeof(ph
), NULL
);
2041 zend_declare_property_bool(php_pqconn_class_entry
, ZEND_STRL("busy"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2042 ph
.read
= php_pqconn_object_read_busy
;
2043 zend_hash_add(&php_pqconn_object_prophandlers
, "busy", sizeof("busy"), (void *) &ph
, sizeof(ph
), NULL
);
2045 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("encoding"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2046 ph
.read
= php_pqconn_object_read_encoding
;
2047 ph
.write
= php_pqconn_object_write_encoding
;
2048 zend_hash_add(&php_pqconn_object_prophandlers
, "encoding", sizeof("encoding"), (void *) &ph
, sizeof(ph
), NULL
);
2051 zend_declare_property_bool(php_pqconn_class_entry
, ZEND_STRL("unbuffered"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2052 ph
.read
= php_pqconn_object_read_unbuffered
;
2053 ph
.write
= php_pqconn_object_write_unbuffered
;
2054 zend_hash_add(&php_pqconn_object_prophandlers
, "unbuffered", sizeof("unbuffered"), (void *) &ph
, sizeof(ph
), NULL
);
2057 zend_declare_property_bool(php_pqconn_class_entry
, ZEND_STRL("nonblocking"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2058 ph
.read
= php_pqconn_object_read_nonblocking
;
2059 ph
.write
= php_pqconn_object_write_nonblocking
;
2060 zend_hash_add(&php_pqconn_object_prophandlers
, "nonblocking", sizeof("nonblocking"), (void *) &ph
, sizeof(ph
), NULL
);
2063 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("db"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2064 ph
.read
= php_pqconn_object_read_db
;
2065 zend_hash_add(&php_pqconn_object_prophandlers
, "db", sizeof("db"), (void *) &ph
, sizeof(ph
), NULL
);
2067 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("user"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2068 ph
.read
= php_pqconn_object_read_user
;
2069 zend_hash_add(&php_pqconn_object_prophandlers
, "user", sizeof("user"), (void *) &ph
, sizeof(ph
), NULL
);
2071 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("pass"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2072 ph
.read
= php_pqconn_object_read_pass
;
2073 zend_hash_add(&php_pqconn_object_prophandlers
, "pass", sizeof("pass"), (void *) &ph
, sizeof(ph
), NULL
);
2075 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("host"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2076 ph
.read
= php_pqconn_object_read_host
;
2077 zend_hash_add(&php_pqconn_object_prophandlers
, "host", sizeof("host"), (void *) &ph
, sizeof(ph
), NULL
);
2079 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("port"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2080 ph
.read
= php_pqconn_object_read_port
;
2081 zend_hash_add(&php_pqconn_object_prophandlers
, "port", sizeof("port"), (void *) &ph
, sizeof(ph
), NULL
);
2084 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("params"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2085 ph
.read
= php_pqconn_object_read_params
;
2086 zend_hash_add(&php_pqconn_object_prophandlers
, "params", sizeof("params"), (void *) &ph
, sizeof(ph
), NULL
);
2089 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("options"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2090 ph
.read
= php_pqconn_object_read_options
;
2091 zend_hash_add(&php_pqconn_object_prophandlers
, "options", sizeof("options"), (void *) &ph
, sizeof(ph
), NULL
);
2093 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC TSRMLS_CC
);
2094 ph
.read
= php_pqconn_object_read_event_handlers
;
2095 zend_hash_add(&php_pqconn_object_prophandlers
, "eventHandlers", sizeof("eventHandlers"), (void *) &ph
, sizeof(ph
), NULL
);
2097 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("defaultFetchType"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2098 ph
.read
= php_pqconn_object_read_def_fetch_type
;
2099 ph
.write
= php_pqconn_object_write_def_fetch_type
;
2100 zend_hash_add(&php_pqconn_object_prophandlers
, "defaultFetchType", sizeof("defaultFetchType"), (void *) &ph
, sizeof(ph
), NULL
);
2103 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("defaultTransactionIsolation"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2104 ph
.read
= php_pqconn_object_read_def_txn_isolation
;
2105 ph
.write
= php_pqconn_object_write_def_txn_isolation
;
2106 zend_hash_add(&php_pqconn_object_prophandlers
, "defaultTransactionIsolation", sizeof("defaultTransactionIsolation"), (void *) &ph
, sizeof(ph
), NULL
);
2109 zend_declare_property_bool(php_pqconn_class_entry
, ZEND_STRL("defaultTransactionReadonly"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2110 ph
.read
= php_pqconn_object_read_def_txn_readonly
;
2111 ph
.write
= php_pqconn_object_write_def_txn_readonly
;
2112 zend_hash_add(&php_pqconn_object_prophandlers
, "defaultTransactionReadonly", sizeof("defaultTransactionReadonly"), (void *) &ph
, sizeof(ph
), NULL
);
2115 zend_declare_property_bool(php_pqconn_class_entry
, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2116 ph
.read
= php_pqconn_object_read_def_txn_deferrable
;
2117 ph
.write
= php_pqconn_object_write_def_txn_deferrable
;
2118 zend_hash_add(&php_pqconn_object_prophandlers
, "defaultTransactionDeferrable", sizeof("defaultTransactionDeferrable"), (void *) &ph
, sizeof(ph
), NULL
);
2121 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("defaultAutoConvert"), PHP_PQRES_CONV_ALL
, ZEND_ACC_PUBLIC TSRMLS_CC
);
2122 ph
.read
= php_pqconn_object_read_def_auto_conv
;
2123 ph
.write
= php_pqconn_object_write_def_auto_conv
;
2124 zend_hash_add(&php_pqconn_object_prophandlers
, "defaultAutoConvert", sizeof("defaultAutoConvert"), (void *) &ph
, sizeof(ph
), NULL
);
2127 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC
);
2128 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC
);
2129 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC
);
2130 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC
);
2131 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC
);
2132 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC
);
2133 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC
);
2134 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC
);
2136 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC
);
2137 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC
);
2138 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC
);
2139 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC
);
2140 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC
);
2142 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC
);
2143 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC
);
2144 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC
);
2145 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC
);
2147 zend_declare_class_constant_stringl(php_pqconn_class_entry
, ZEND_STRL("EVENT_NOTICE"), ZEND_STRL("notice") TSRMLS_CC
);
2148 zend_declare_class_constant_stringl(php_pqconn_class_entry
, ZEND_STRL("EVENT_RESULT"), ZEND_STRL("result") TSRMLS_CC
);
2149 zend_declare_class_constant_stringl(php_pqconn_class_entry
, ZEND_STRL("EVENT_RESET"), ZEND_STRL("reset") TSRMLS_CC
);
2151 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("ASYNC"), 0x1 TSRMLS_CC
);
2152 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("PERSISTENT"), 0x2 TSRMLS_CC
);
2162 * vim600: noet sw=4 ts=4 fdm=marker
2163 * vim<600: noet sw=4 ts=4