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 #if PHP_PQ_HAVE_PHP_JSON_H
20 #include <php_json.h> /* we've added the include directory to INCLUDES */
23 #include <Zend/zend_smart_str.h>
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
);
40 static int apply_to_oid(zval
*ztype
, void *arg
)
44 **types
= zval_get_long(ztype
);
47 return ZEND_HASH_APPLY_KEEP
;
50 unsigned php_pq_params_set_type_oids(php_pq_params_t
*p
, HashTable
*oids
)
52 p
->type
.count
= oids
? zend_hash_num_elements(oids
) : 0;
59 Oid
*ptr
= ecalloc(p
->type
.count
+ 1, sizeof(*p
->type
.oids
));
60 /* +1 for when less types than params are specified */
62 zend_hash_apply_with_argument(oids
, apply_to_oid
, &ptr
);
67 unsigned php_pq_params_add_type_oid(php_pq_params_t
*p
, Oid type
)
69 p
->type
.oids
= safe_erealloc(p
->type
.oids
, ++p
->type
.count
, sizeof(*p
->type
.oids
), sizeof(*p
->type
.oids
));
70 p
->type
.oids
[p
->type
.count
] = 0;
71 p
->type
.oids
[p
->type
.count
-1] = type
;
76 static zend_string
*object_param_to_string(php_pq_params_t
*p
, zval
*zobj
, Oid type
)
78 #if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
83 #if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
84 # ifdef PHP_PQ_OID_JSONB
85 case PHP_PQ_OID_JSONB
:
88 # if PHP_VERSION_ID >= 70100
89 JSON_G(encode_max_depth
) = PHP_JSON_PARSER_DEFAULT_DEPTH
;
91 php_json_encode(&str
, zobj
, PHP_JSON_UNESCAPED_UNICODE
);
97 return php_pqdt_to_string(zobj
, "Y-m-d");
98 #ifdef PHP_PQ_OID_ABSTIME
99 case PHP_PQ_OID_ABSTIME
:
100 return php_pqdt_to_string(zobj
, "Y-m-d H:i:s");
102 case PHP_PQ_OID_TIMESTAMP
:
103 return php_pqdt_to_string(zobj
, "Y-m-d H:i:s.u");
105 case PHP_PQ_OID_TIMESTAMPTZ
:
106 return php_pqdt_to_string(zobj
, "Y-m-d H:i:s.uO");
109 return zval_get_string(zobj
);
112 struct apply_to_param_from_array_arg
{
113 php_pq_params_t
*params
;
121 static int apply_to_param_from_array(zval
*zparam
, void *arg_ptr
)
123 struct apply_to_param_from_array_arg subarg
, *arg
= arg_ptr
;
126 zend_string
*str
, *tmpstr
;
129 smart_str_appendc(arg
->buffer
, arg
->delim
);
135 ZVAL_LONG(&ztype
, arg
->type
);
136 zend_call_method_with_2_params(arg
->zconv
, NULL
, NULL
, "converttostring", &rv
, zparam
, &ztype
);
137 tmpstr
= zval_get_string(&rv
);
143 switch (Z_TYPE_P(zparam
)) {
149 smart_str_appends(arg
->buffer
, "NULL");
153 smart_str_appends(arg
->buffer
, "t");
157 smart_str_appends(arg
->buffer
, "f");
161 smart_str_append_long(arg
->buffer
, Z_LVAL_P(zparam
));
165 len
= spprintf(&tmp
, 0, "%F", Z_DVAL_P(zparam
));
166 smart_str_appendl(arg
->buffer
, tmp
, len
);
173 smart_str_appendc(arg
->buffer
, '{');
174 zend_hash_apply_with_argument(Z_ARRVAL_P(zparam
), apply_to_param_from_array
, &subarg
);
175 smart_str_appendc(arg
->buffer
, '}');
179 if ((tmpstr
= object_param_to_string(arg
->params
, zparam
, arg
->type
))) {
184 tmpstr
= zval_get_string(zparam
);
187 #if PHP_VERSION_ID < 70300
188 str
= php_addslashes(tmpstr
, 1);
190 str
= php_addslashes(tmpstr
);
191 zend_string_release(tmpstr
);
193 smart_str_appendc(arg
->buffer
, '"');
194 smart_str_appendl(arg
->buffer
, str
->val
, str
->len
);
195 smart_str_appendc(arg
->buffer
, '"');
196 zend_string_release(str
);
201 return ZEND_HASH_APPLY_KEEP
;
204 static zend_string
*array_param_to_string(php_pq_params_t
*p
, zval
*zarr
, Oid type
)
207 struct apply_to_param_from_array_arg arg
= {NULL
};
210 #if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON)
211 # ifdef PHP_PQ_OID_JSONB
212 case PHP_PQ_OID_JSONB
:
214 case PHP_PQ_OID_JSON
:
215 php_json_encode(&s
, zarr
, PHP_JSON_UNESCAPED_UNICODE
);
222 arg
.type
= PHP_PQ_TYPE_OF_ARRAY(type
);
223 arg
.delim
= PHP_PQ_DELIM_OF_ARRAY(type
);
224 arg
.zconv
= zend_hash_index_find(&p
->type
.conv
, PHP_PQ_TYPE_OF_ARRAY(type
));
225 smart_str_appendc(arg
.buffer
, '{');
227 zend_hash_apply_with_argument(Z_ARRVAL_P(zarr
), apply_to_param_from_array
, &arg
);
228 smart_str_appendc(arg
.buffer
, '}');
236 static void php_pq_params_set_param(php_pq_params_t
*p
, unsigned index
, zval
*zpp
)
239 Oid type
= p
->type
.count
> index
? p
->type
.oids
[index
] : 0;
241 if (type
&& (zconv
= zend_hash_index_find(&p
->type
.conv
, type
))) {
245 ZVAL_LONG(&ztype
, type
);
246 zend_call_method_with_2_params(zconv
, NULL
, NULL
, "converttostring", &rv
, zpp
, &ztype
);
247 convert_to_string(&rv
);
248 p
->param
.strings
[index
] = Z_STRVAL_P(&rv
);
249 zend_hash_next_index_insert(&p
->param
.dtor
, &rv
);
252 zend_string
*str
= NULL
;
257 switch (Z_TYPE_P(zpp
)) {
263 p
->param
.strings
[index
] = NULL
;
267 p
->param
.strings
[index
] = "t";
271 p
->param
.strings
[index
] = "f";
275 tmp_len
= slprintf(tmp_str
, sizeof(tmp_str
), "%F", Z_DVAL_P(zpp
));
276 str
= zend_string_init(tmp_str
, tmp_len
, 0);
280 str
= array_param_to_string(p
, zpp
, type
);
284 if ((str
= object_param_to_string(p
, zpp
, type
))) {
289 str
= zval_get_string(zpp
);
295 p
->param
.strings
[index
] = Z_STRVAL(tmp
);
296 zend_hash_next_index_insert(&p
->param
.dtor
, &tmp
);
301 struct apply_to_params_arg
{
302 php_pq_params_t
*params
;
306 static int apply_to_params(zval
*zp
, void *arg_ptr
)
308 struct apply_to_params_arg
*arg
= arg_ptr
;
310 SEPARATE_ZVAL_IF_NOT_REF(zp
);
311 php_pq_params_set_param(arg
->params
, arg
->index
++, zp
);
312 return ZEND_HASH_APPLY_KEEP
;
315 unsigned php_pq_params_add_param(php_pq_params_t
*p
, zval
*param
)
317 p
->param
.strings
= safe_erealloc(p
->param
.strings
, ++p
->param
.count
, sizeof(*p
->param
.strings
), 0);
318 php_pq_params_set_param(p
, p
->param
.count
-1, param
);
319 return p
->type
.count
;
322 unsigned php_pq_params_set_params(php_pq_params_t
*p
, HashTable
*params
)
324 p
->param
.count
= params
? zend_hash_num_elements(params
) : 0;
326 if (p
->param
.strings
) {
327 efree(p
->param
.strings
);
328 p
->param
.strings
= NULL
;
330 zend_hash_clean(&p
->param
.dtor
);
331 if (p
->param
.count
) {
332 struct apply_to_params_arg arg
= {p
, 0};
333 p
->param
.strings
= ecalloc(p
->param
.count
, sizeof(*p
->param
.strings
));
334 zend_hash_apply_with_argument(params
, apply_to_params
, &arg
);
336 return p
->param
.count
;
339 void php_pq_params_free(php_pq_params_t
**p
)
342 php_pq_params_set_type_oids(*p
, NULL
);
343 php_pq_params_set_params(*p
, NULL
);
345 zend_hash_destroy(&(*p
)->param
.dtor
);
346 zend_hash_destroy(&(*p
)->type
.conv
);
353 php_pq_params_t
*php_pq_params_init(HashTable
*conv
, HashTable
*oids
, HashTable
*params
)
355 php_pq_params_t
*p
= ecalloc(1, sizeof(*p
));
357 zend_hash_init(&p
->type
.conv
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
358 zend_hash_init(&p
->param
.dtor
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
361 php_pq_params_set_type_conv(p
, conv
);
364 php_pq_params_set_type_oids(p
, oids
);
367 php_pq_params_set_params(p
, params
);
378 * vim600: noet sw=4 ts=4 fdm=marker
379 * vim<600: noet sw=4 ts=4