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 #if PHP_PQ_HAVE_PHP_JSON_H
21 #include <php_json.h> /* we've added the include directory to INCLUDES */
24 #include <Zend/zend_interfaces.h>
29 #include "php_pq_params.h"
30 #include "php_pq_misc.h"
32 #include "php_pq_type.h"
34 void php_pq_params_set_type_conv(php_pq_params_t
*p
, HashTable
*conv
)
36 zend_hash_clean(&p
->type
.conv
);
37 zend_hash_copy(&p
->type
.conv
, conv
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
40 static int apply_to_oid(void *p
, void *arg TSRMLS_DC
)
45 if (Z_TYPE_PP(ztype
) != IS_LONG
) {
46 convert_to_long_ex(ztype
);
49 **types
= Z_LVAL_PP(ztype
);
52 if (*ztype
!= *(zval
**)p
) {
55 return ZEND_HASH_APPLY_KEEP
;
58 unsigned php_pq_params_set_type_oids(php_pq_params_t
*p
, HashTable
*oids
)
60 p
->type
.count
= oids
? zend_hash_num_elements(oids
) : 0;
68 Oid
*ptr
= ecalloc(p
->type
.count
+ 1, sizeof(*p
->type
.oids
));
69 /* +1 for when less types than params are specified */
71 zend_hash_apply_with_argument(oids
, apply_to_oid
, &ptr TSRMLS_CC
);
76 unsigned php_pq_params_add_type_oid(php_pq_params_t
*p
, Oid type
)
78 p
->type
.oids
= safe_erealloc(p
->type
.oids
, ++p
->type
.count
, sizeof(*p
->type
.oids
), sizeof(*p
->type
.oids
));
79 p
->type
.oids
[p
->type
.count
] = 0;
80 p
->type
.oids
[p
->type
.count
-1] = type
;
85 static zval
*object_param_to_string(php_pq_params_t
*p
, zval
*zobj
, Oid type TSRMLS_DC
)
87 zval
*return_value
= NULL
;
91 #if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
92 # ifdef PHP_PQ_OID_JSONB
93 case PHP_PQ_OID_JSONB
:
96 php_json_encode(&str
, zobj
, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC
);
101 case PHP_PQ_OID_DATE
:
102 php_pqdt_to_string(zobj
, "Y-m-d", &str
.c
, &str
.len TSRMLS_CC
);
105 case PHP_PQ_OID_ABSTIME
:
106 php_pqdt_to_string(zobj
, "Y-m-d H:i:s", &str
.c
, &str
.len TSRMLS_CC
);
109 case PHP_PQ_OID_TIMESTAMP
:
110 php_pqdt_to_string(zobj
, "Y-m-d H:i:s.u", &str
.c
, &str
.len TSRMLS_CC
);
113 case PHP_PQ_OID_TIMESTAMPTZ
:
114 php_pqdt_to_string(zobj
, "Y-m-d H:i:s.uO", &str
.c
, &str
.len TSRMLS_CC
);
118 MAKE_STD_ZVAL(return_value
);
119 MAKE_COPY_ZVAL(&zobj
, return_value
);
120 convert_to_string(return_value
);
125 MAKE_STD_ZVAL(return_value
);
126 RETVAL_STRINGL(str
.c
, str
.len
, 0);
132 struct apply_to_param_from_array_arg
{
133 php_pq_params_t
*params
;
141 static int apply_to_param_from_array(void *ptr
, void *arg_ptr TSRMLS_DC
)
143 struct apply_to_param_from_array_arg subarg
, *arg
= arg_ptr
;
144 zval
*ztmp
, **zparam
= ptr
, *zcopy
= *zparam
;
150 smart_str_appendc(arg
->buffer
, arg
->delim
);
154 zval
*ztype
, *rv
= NULL
;
156 MAKE_STD_ZVAL(ztype
);
157 ZVAL_LONG(ztype
, arg
->type
);
158 zend_call_method_with_2_params(arg
->zconv
, NULL
, NULL
, "converttostring", &rv
, zcopy
, ztype
);
159 zval_ptr_dtor(&ztype
);
162 convert_to_string(rv
);
165 return ZEND_HASH_APPLY_STOP
;
171 switch (Z_TYPE_P(zcopy
)) {
173 smart_str_appends(arg
->buffer
, "NULL");
177 smart_str_appends(arg
->buffer
, Z_BVAL_P(zcopy
) ? "t" : "f");
181 smart_str_append_long(arg
->buffer
, Z_LVAL_P(zcopy
));
185 len
= spprintf(&tmp
, 0, "%F", Z_DVAL_P(zcopy
));
186 smart_str_appendl(arg
->buffer
, tmp
, len
);
193 smart_str_appendc(arg
->buffer
, '{');
194 zend_hash_apply_with_argument(Z_ARRVAL_P(zcopy
), apply_to_param_from_array
, &subarg TSRMLS_CC
);
195 smart_str_appendc(arg
->buffer
, '}');
199 if ((ztmp
= object_param_to_string(arg
->params
, zcopy
, arg
->type TSRMLS_CC
))) {
204 SEPARATE_ZVAL(&zcopy
);
205 convert_to_string(zcopy
);
208 tmp
= php_addslashes(Z_STRVAL_P(zcopy
), Z_STRLEN_P(zcopy
), &tmp_len
, 0 TSRMLS_CC
);
209 smart_str_appendc(arg
->buffer
, '"');
210 smart_str_appendl(arg
->buffer
, tmp
, tmp_len
);
211 smart_str_appendc(arg
->buffer
, '"');
213 if (zcopy
!= *zparam
) {
214 zval_ptr_dtor(&zcopy
);
221 return ZEND_HASH_APPLY_KEEP
;
224 static zval
*array_param_to_string(php_pq_params_t
*p
, zval
*zarr
, Oid type TSRMLS_DC
)
226 zval
*zcopy
, *return_value
;
228 struct apply_to_param_from_array_arg arg
= {NULL
};
231 #if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
232 # ifdef PHP_PQ_OID_JSONB
233 case PHP_PQ_OID_JSONB
:
235 case PHP_PQ_OID_JSON
:
236 php_json_encode(&s
, zarr
, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC
);
244 arg
.type
= PHP_PQ_TYPE_OF_ARRAY(type
);
245 arg
.delim
= PHP_PQ_DELIM_OF_ARRAY(type
);
246 zend_hash_index_find(&p
->type
.conv
, PHP_PQ_TYPE_OF_ARRAY(type
), (void *) &arg
.zconv
);
247 smart_str_appendc(arg
.buffer
, '{');
248 MAKE_STD_ZVAL(zcopy
);
249 MAKE_COPY_ZVAL(&zarr
, zcopy
);
250 zend_hash_apply_with_argument(Z_ARRVAL_P(zcopy
), apply_to_param_from_array
, &arg TSRMLS_CC
);
251 zval_ptr_dtor(&zcopy
);
252 smart_str_appendc(arg
.buffer
, '}');
257 /* must not return NULL */
258 MAKE_STD_ZVAL(return_value
);
261 RETVAL_STRINGL(s
.c
, s
.len
, 0);
263 RETVAL_EMPTY_STRING();
269 static void php_pq_params_set_param(php_pq_params_t
*p
, unsigned index
, zval
**zpp
)
272 Oid type
= p
->type
.count
> index
? p
->type
.oids
[index
] : 0;
275 if (type
&& SUCCESS
== zend_hash_index_find(&p
->type
.conv
, type
, (void *) &zconv
)) {
276 zval
*ztype
, *rv
= NULL
;
278 MAKE_STD_ZVAL(ztype
);
279 ZVAL_LONG(ztype
, type
);
280 zend_call_method_with_2_params(zconv
, NULL
, NULL
, "converttostring", &rv
, *zpp
, ztype
);
281 zval_ptr_dtor(&ztype
);
283 convert_to_string(rv
);
284 p
->param
.strings
[index
] = Z_STRVAL_P(rv
);
285 zend_hash_next_index_insert(&p
->param
.dtor
, (void *) &rv
, sizeof(zval
*), NULL
);
288 zval
*tmp
, *zcopy
= *zpp
;
290 switch (Z_TYPE_P(zcopy
)) {
292 p
->param
.strings
[index
] = NULL
;
296 p
->param
.strings
[index
] = Z_BVAL_P(zcopy
) ? "t" : "f";
300 MAKE_STD_ZVAL(zcopy
);
301 MAKE_COPY_ZVAL(zpp
, zcopy
);
302 Z_TYPE_P(zcopy
) = IS_STRING
;
303 Z_STRLEN_P(zcopy
) = spprintf(&Z_STRVAL_P(zcopy
), 0, "%F", Z_DVAL_PP(zpp
));
307 MAKE_STD_ZVAL(zcopy
);
308 MAKE_COPY_ZVAL(zpp
, zcopy
);
309 tmp
= array_param_to_string(p
, zcopy
, type TSRMLS_CC
);
310 zval_ptr_dtor(&zcopy
);
315 if ((tmp
= object_param_to_string(p
, zcopy
, type TSRMLS_CC
))) {
322 convert_to_string_ex(&zcopy
);
326 p
->param
.strings
[index
] = Z_STRVAL_P(zcopy
);
329 zend_hash_next_index_insert(&p
->param
.dtor
, (void *) &zcopy
, sizeof(zval
*), NULL
);
334 struct apply_to_params_arg
{
335 php_pq_params_t
*params
;
339 static int apply_to_params(void *zp
, void *arg_ptr TSRMLS_DC
)
341 struct apply_to_params_arg
*arg
= arg_ptr
;
343 SEPARATE_ZVAL_IF_NOT_REF((zval
**) zp
);
344 php_pq_params_set_param(arg
->params
, arg
->index
++, zp
);
345 return ZEND_HASH_APPLY_KEEP
;
348 unsigned php_pq_params_add_param(php_pq_params_t
*p
, zval
*param
)
350 p
->param
.strings
= safe_erealloc(p
->param
.strings
, ++p
->param
.count
, sizeof(*p
->param
.strings
), 0);
351 php_pq_params_set_param(p
, p
->param
.count
-1, ¶m
);
352 return p
->type
.count
;
355 unsigned php_pq_params_set_params(php_pq_params_t
*p
, HashTable
*params
)
357 p
->param
.count
= params
? zend_hash_num_elements(params
) : 0;
360 if (p
->param
.strings
) {
361 efree(p
->param
.strings
);
362 p
->param
.strings
= NULL
;
364 zend_hash_clean(&p
->param
.dtor
);
365 if (p
->param
.count
) {
366 struct apply_to_params_arg arg
= {p
, 0};
367 p
->param
.strings
= ecalloc(p
->param
.count
, sizeof(*p
->param
.strings
));
368 zend_hash_apply_with_argument(params
, apply_to_params
, &arg TSRMLS_CC
);
370 return p
->param
.count
;
373 void php_pq_params_free(php_pq_params_t
**p
)
376 php_pq_params_set_type_oids(*p
, NULL
);
377 php_pq_params_set_params(*p
, NULL
);
379 zend_hash_destroy(&(*p
)->param
.dtor
);
380 zend_hash_destroy(&(*p
)->type
.conv
);
387 php_pq_params_t
*php_pq_params_init(HashTable
*conv
, HashTable
*oids
, HashTable
*params TSRMLS_DC
)
389 php_pq_params_t
*p
= ecalloc(1, sizeof(*p
));
392 zend_hash_init(&p
->type
.conv
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
393 zend_hash_init(&p
->param
.dtor
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
396 php_pq_params_set_type_conv(p
, conv
);
399 php_pq_params_set_type_oids(p
, oids
);
402 php_pq_params_set_params(p
, params
);
413 * vim600: noet sw=4 ts=4 fdm=marker
414 * vim<600: noet sw=4 ts=4