2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
18 #include <ext/standard/php_string.h>
19 #include <ext/standard/php_smart_str.h>
20 #include <ext/json/php_json.h>
22 #include <Zend/zend_interfaces.h>
27 #include "php_pq_params.h"
28 #include "php_pq_misc.h"
30 #include "php_pq_type.h"
32 void php_pq_params_set_type_conv(php_pq_params_t
*p
, HashTable
*conv
)
34 zend_hash_clean(&p
->type
.conv
);
35 zend_hash_copy(&p
->type
.conv
, conv
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
38 static int apply_to_oid(void *p
, void *arg TSRMLS_DC
)
43 if (Z_TYPE_PP(ztype
) != IS_LONG
) {
44 convert_to_long_ex(ztype
);
47 **types
= Z_LVAL_PP(ztype
);
50 if (*ztype
!= *(zval
**)p
) {
53 return ZEND_HASH_APPLY_KEEP
;
56 unsigned php_pq_params_set_type_oids(php_pq_params_t
*p
, HashTable
*oids
)
58 p
->type
.count
= oids
? zend_hash_num_elements(oids
) : 0;
66 Oid
*ptr
= ecalloc(p
->type
.count
+ 1, sizeof(*p
->type
.oids
));
67 /* +1 for when less types than params are specified */
69 zend_hash_apply_with_argument(oids
, apply_to_oid
, &ptr TSRMLS_CC
);
74 unsigned php_pq_params_add_type_oid(php_pq_params_t
*p
, Oid type
)
76 p
->type
.oids
= safe_erealloc(p
->type
.oids
, ++p
->type
.count
, sizeof(*p
->type
.oids
), sizeof(*p
->type
.oids
));
77 p
->type
.oids
[p
->type
.count
] = 0;
78 p
->type
.oids
[p
->type
.count
-1] = type
;
83 static zval
*object_param_to_string(php_pq_params_t
*p
, zval
*zobj
, Oid type TSRMLS_DC
)
85 zval
*return_value
= NULL
;
89 #ifdef PHP_PQ_OID_JSON
90 # ifdef PHP_PQ_OID_JSONB
91 case PHP_PQ_OID_JSONB
:
94 php_json_encode(&str
, zobj
, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC
);
100 php_pqdt_to_string(zobj
, "Y-m-d", &str
.c
, &str
.len TSRMLS_CC
);
103 case PHP_PQ_OID_ABSTIME
:
104 php_pqdt_to_string(zobj
, "Y-m-d H:i:s", &str
.c
, &str
.len TSRMLS_CC
);
107 case PHP_PQ_OID_TIMESTAMP
:
108 php_pqdt_to_string(zobj
, "Y-m-d H:i:s.u", &str
.c
, &str
.len TSRMLS_CC
);
111 case PHP_PQ_OID_TIMESTAMPTZ
:
112 php_pqdt_to_string(zobj
, "Y-m-d H:i:s.uO", &str
.c
, &str
.len TSRMLS_CC
);
116 SEPARATE_ZVAL(&zobj
);
117 convert_to_string(zobj
);
123 MAKE_STD_ZVAL(return_value
);
124 RETVAL_STRINGL(str
.c
, str
.len
, 0);
130 static int apply_to_param_from_array(void *ptr TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
132 php_pq_params_t
*p
= va_arg(argv
, php_pq_params_t
*);
133 unsigned j
, *i
= va_arg(argv
, unsigned *);
134 smart_str
*s
= va_arg(argv
, smart_str
*);
135 Oid type
= va_arg(argv
, Oid
);
136 zval
*ztmp
, **zparam
= ptr
, *zcopy
= *zparam
, **zconv
= va_arg(argv
, zval
**);
142 smart_str_appendc(s
, ',');
148 zend_call_method_with_1_params(zconv
, NULL
, NULL
, "converttostring", &rv
, zcopy
);
149 convert_to_string(rv
);
153 switch (Z_TYPE_P(zcopy
)) {
155 smart_str_appends(s
, "NULL");
159 smart_str_appends(s
, Z_BVAL_P(zcopy
) ? "t" : "f");
163 smart_str_append_long(s
, Z_LVAL_P(zcopy
));
167 len
= spprintf(&tmp
, 0, "%F", Z_DVAL_P(zcopy
));
168 smart_str_appendl(s
, tmp
, len
);
174 smart_str_appendc(s
, '{');
175 zend_hash_apply_with_arguments(Z_ARRVAL_P(zcopy
) TSRMLS_CC
, apply_to_param_from_array
, 5, p
, &j
, s
, type
, zconv
);
176 smart_str_appendc(s
, '}');
180 if ((ztmp
= object_param_to_string(p
, zcopy
, type TSRMLS_CC
))) {
185 SEPARATE_ZVAL(&zcopy
);
186 convert_to_string(zcopy
);
189 tmp
= php_addslashes(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
), &tmp_len
, 0 TSRMLS_CC
);
190 smart_str_appendc(s
, '"');
191 smart_str_appendl(s
, tmp
, tmp_len
);
192 smart_str_appendc(s
, '"');
194 if (zcopy
!= *zparam
) {
195 zval_ptr_dtor(&zcopy
);
202 return ZEND_HASH_APPLY_KEEP
;
205 static zval
*array_param_to_string(php_pq_params_t
*p
, zval
*zarr
, Oid type TSRMLS_DC
)
207 zval
*return_value
, **zconv
= NULL
;
212 #ifdef PHP_PQ_OID_JSON
213 # ifdef PHP_PQ_OID_JSONB
214 case PHP_PQ_OID_JSONB
:
216 case PHP_PQ_OID_JSON
:
217 php_json_encode(&s
, zarr
, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC
);
223 zend_hash_index_find(&p
->type
.conv
, PHP_PQ_TYPE_OF_ARRAY(type
), (void *) &zconv
);
225 smart_str_appendc(&s
, '{');
226 zend_hash_apply_with_arguments(Z_ARRVAL_P(zarr
) TSRMLS_CC
, apply_to_param_from_array
, 5, p
, &i
, &s
, (Oid
) PHP_PQ_TYPE_OF_ARRAY(type
), zconv
);
227 smart_str_appendc(&s
, '}');
232 /* must not return NULL */
233 MAKE_STD_ZVAL(return_value
);
236 RETVAL_STRINGL(s
.c
, s
.len
, 0);
238 RETVAL_EMPTY_STRING();
244 static void php_pq_params_set_param(php_pq_params_t
*p
, unsigned index
, zval
**zpp
)
247 Oid type
= p
->type
.count
> index
? p
->type
.oids
[index
] : 0;
250 if (type
&& SUCCESS
== zend_hash_index_find(&p
->type
.conv
, type
, (void *) &zconv
)) {
253 zend_call_method_with_1_params(zconv
, NULL
, NULL
, "converttostring", &rv
, *zpp
);
254 convert_to_string(rv
);
255 p
->param
.strings
[index
] = Z_STRVAL_P(rv
);
256 zend_hash_next_index_insert(&p
->param
.dtor
, (void *) &rv
, sizeof(zval
*), NULL
);
258 zval
*tmp
, *zcopy
= *zpp
;
260 switch (Z_TYPE_P(zcopy
)) {
262 p
->param
.strings
[index
] = NULL
;
266 p
->param
.strings
[index
] = Z_BVAL_P(zcopy
) ? "t" : "f";
270 SEPARATE_ZVAL(&zcopy
);
271 Z_TYPE_P(zcopy
) = IS_STRING
;
272 Z_STRLEN_P(zcopy
) = spprintf(&Z_STRVAL_P(zcopy
), 0, "%F", Z_DVAL_PP(zpp
));
276 zcopy
= array_param_to_string(p
, zcopy
, type TSRMLS_CC
);
280 if ((tmp
= object_param_to_string(p
, zcopy
, type TSRMLS_CC
))) {
287 convert_to_string_ex(&zcopy
);
291 p
->param
.strings
[index
] = Z_STRVAL_P(zcopy
);
294 zend_hash_next_index_insert(&p
->param
.dtor
, (void *) &zcopy
, sizeof(zval
*), NULL
);
299 static int apply_to_params(void *zp TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
301 php_pq_params_t
*p
= (php_pq_params_t
*) va_arg(argv
, php_pq_params_t
*);
302 unsigned *index
= (unsigned *) va_arg(argv
, unsigned *);
304 php_pq_params_set_param(p
, (*index
)++, zp
);
305 return ZEND_HASH_APPLY_KEEP
;
308 unsigned php_pq_params_add_param(php_pq_params_t
*p
, zval
*param
)
310 p
->param
.strings
= safe_erealloc(p
->param
.strings
, ++p
->param
.count
, sizeof(*p
->param
.strings
), 0);
311 php_pq_params_set_param(p
, p
->param
.count
-1, ¶m
);
312 return p
->type
.count
;
315 unsigned php_pq_params_set_params(php_pq_params_t
*p
, HashTable
*params
)
317 p
->param
.count
= params
? zend_hash_num_elements(params
) : 0;
320 if (p
->param
.strings
) {
321 efree(p
->param
.strings
);
322 p
->param
.strings
= NULL
;
324 zend_hash_clean(&p
->param
.dtor
);
325 if (p
->param
.count
) {
327 p
->param
.strings
= ecalloc(p
->param
.count
, sizeof(*p
->param
.strings
));
328 zend_hash_apply_with_arguments(params TSRMLS_CC
, apply_to_params
, 2, p
, &index
);
330 return p
->param
.count
;
333 void php_pq_params_free(php_pq_params_t
**p
)
336 php_pq_params_set_type_oids(*p
, NULL
);
337 php_pq_params_set_params(*p
, NULL
);
339 zend_hash_destroy(&(*p
)->param
.dtor
);
340 zend_hash_destroy(&(*p
)->type
.conv
);
347 php_pq_params_t
*php_pq_params_init(HashTable
*conv
, HashTable
*oids
, HashTable
*params TSRMLS_DC
)
349 php_pq_params_t
*p
= ecalloc(1, sizeof(*p
));
352 zend_hash_init(&p
->type
.conv
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
353 zend_hash_init(&p
->param
.dtor
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
356 php_pq_params_set_type_conv(p
, conv
);
359 php_pq_params_set_type_oids(p
, oids
);
362 php_pq_params_set_params(p
, params
);
373 * vim600: noet sw=4 ts=4 fdm=marker
374 * vim<600: noet sw=4 ts=4