X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pq_params.c;h=a691eebd62464efbe897c2f91533c064b7f85961;hp=ec915829ed7146bf03911fd7f6eb93d69ddfdaf6;hb=63fb773601422aa39375d8effb9f37abab981804;hpb=0bce4e6693c3077acc32f833442769cc7de121ef diff --git a/src/php_pq_params.c b/src/php_pq_params.c index ec91582..a691eeb 100644 --- a/src/php_pq_params.c +++ b/src/php_pq_params.c @@ -16,43 +16,40 @@ #include #include -#include +#if PHP_PQ_HAVE_PHP_JSON_H +#include /* we've added the include directory to INCLUDES */ +#endif +#include #include #include #include "php_pq.h" #include "php_pq_params.h" +#include "php_pq_misc.h" +#undef PHP_PQ_TYPE +#include "php_pq_type.h" void php_pq_params_set_type_conv(php_pq_params_t *p, HashTable *conv) { zend_hash_clean(&p->type.conv); - zend_hash_copy(&p->type.conv, conv, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + zend_hash_copy(&p->type.conv, conv, (copy_ctor_func_t) zval_add_ref); } -static int apply_to_oid(void *p, void *arg TSRMLS_DC) +static int apply_to_oid(zval *ztype, void *arg) { Oid **types = arg; - zval **ztype = p; - - if (Z_TYPE_PP(ztype) != IS_LONG) { - convert_to_long_ex(ztype); - } - **types = Z_LVAL_PP(ztype); + **types = zval_get_long(ztype); ++*types; - if (*ztype != *(zval **)p) { - zval_ptr_dtor(ztype); - } return ZEND_HASH_APPLY_KEEP; } unsigned php_pq_params_set_type_oids(php_pq_params_t *p, HashTable *oids) { p->type.count = oids ? zend_hash_num_elements(oids) : 0; - TSRMLS_DF(p); if (p->type.oids) { efree(p->type.oids); @@ -62,7 +59,7 @@ unsigned php_pq_params_set_type_oids(php_pq_params_t *p, HashTable *oids) Oid *ptr = ecalloc(p->type.count + 1, sizeof(*p->type.oids)); /* +1 for when less types than params are specified */ p->type.oids = ptr; - zend_hash_apply_with_argument(oids, apply_to_oid, &ptr TSRMLS_CC); + zend_hash_apply_with_argument(oids, apply_to_oid, &ptr); } return p->type.count; } @@ -75,173 +72,256 @@ unsigned php_pq_params_add_type_oid(php_pq_params_t *p, Oid type) return p->type.count; } -static int apply_to_param_from_array(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) + +static zend_string *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type) { - zval **zparam = p; - unsigned j, *i = va_arg(argv, unsigned *); - smart_str *s = va_arg(argv, smart_str *); - zval **zconv = va_arg(argv, zval **); +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) + smart_str str = {0}; +#endif + + switch (type) { +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) +# ifdef PHP_PQ_OID_JSONB + case PHP_PQ_OID_JSONB: +# endif + case PHP_PQ_OID_JSON: +# if PHP_VERSION_ID >= 70100 + JSON_G(encode_max_depth) = PHP_JSON_PARSER_DEFAULT_DEPTH; +# endif + php_json_encode(&str, zobj, PHP_JSON_UNESCAPED_UNICODE); + smart_str_0(&str); + return str.s; +#endif + + case PHP_PQ_OID_DATE: + return php_pqdt_to_string(zobj, "Y-m-d"); +#ifdef PHP_PQ_OID_ABSTIME + case PHP_PQ_OID_ABSTIME: + return php_pqdt_to_string(zobj, "Y-m-d H:i:s"); +#endif + case PHP_PQ_OID_TIMESTAMP: + return php_pqdt_to_string(zobj, "Y-m-d H:i:s.u"); + + case PHP_PQ_OID_TIMESTAMPTZ: + return php_pqdt_to_string(zobj, "Y-m-d H:i:s.uO"); + } + + return zval_get_string(zobj); +} + +struct apply_to_param_from_array_arg { + php_pq_params_t *params; + unsigned index; + smart_str *buffer; + Oid type; + char delim; + zval *zconv; +}; + +static int apply_to_param_from_array(zval *zparam, void *arg_ptr) +{ + struct apply_to_param_from_array_arg subarg, *arg = arg_ptr; char *tmp; size_t len; - int tmp_len; + zend_string *str, *tmpstr; - if ((*i)++) { - smart_str_appendc(s, ','); + if (arg->index++) { + smart_str_appendc(arg->buffer, arg->delim); } - if (zconv) { - zval *rv = NULL; + if (arg->zconv) { + zval ztype, rv; - zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, *zparam); - convert_to_string(rv); - smart_str_appendl(s, Z_STRVAL_P(rv), Z_STRLEN_P(rv)); + ZVAL_LONG(&ztype, arg->type); + zend_call_method_with_2_params(arg->zconv, NULL, NULL, "converttostring", &rv, zparam, &ztype); + tmpstr = zval_get_string(&rv); zval_ptr_dtor(&rv); + goto append_string; + } else { - switch (Z_TYPE_PP(zparam)) { + again: + switch (Z_TYPE_P(zparam)) { + case IS_REFERENCE: + ZVAL_DEREF(zparam); + goto again; + case IS_NULL: - smart_str_appends(s, "NULL"); + smart_str_appends(arg->buffer, "NULL"); + break; + + case IS_TRUE: + smart_str_appends(arg->buffer, "t"); break; - case IS_BOOL: - smart_str_appends(s, Z_BVAL_PP(zparam) ? "t" : "f"); + case IS_FALSE: + smart_str_appends(arg->buffer, "f"); break; case IS_LONG: - smart_str_append_long(s, Z_LVAL_PP(zparam)); + smart_str_append_long(arg->buffer, Z_LVAL_P(zparam)); break; case IS_DOUBLE: - len = spprintf(&tmp, 0, "%F", Z_DVAL_PP(zparam)); - smart_str_appendl(s, tmp, len); + len = spprintf(&tmp, 0, "%F", Z_DVAL_P(zparam)); + smart_str_appendl(arg->buffer, tmp, len); efree(tmp); break; case IS_ARRAY: - j = 0; - smart_str_appendc(s, '{'); - zend_hash_apply_with_arguments(Z_ARRVAL_PP(zparam) TSRMLS_CC, apply_to_param_from_array, 2, &j, s, zconv); - smart_str_appendc(s, '}'); + subarg = *arg; + subarg.index = 0; + smart_str_appendc(arg->buffer, '{'); + zend_hash_apply_with_argument(Z_ARRVAL_P(zparam), apply_to_param_from_array, &subarg); + smart_str_appendc(arg->buffer, '}'); break; - default: - SEPARATE_ZVAL(zparam); - if (Z_TYPE_PP(zparam) != IS_STRING) { - convert_to_string(*zparam); + case IS_OBJECT: + if ((tmpstr = object_param_to_string(arg->params, zparam, arg->type))) { + goto append_string; } + /* no break */ + default: + tmpstr = zval_get_string(zparam); - tmp = php_addslashes(Z_STRVAL_PP(zparam), Z_STRLEN_PP(zparam), &tmp_len, 0 TSRMLS_CC); - smart_str_appendc(s, '"'); - smart_str_appendl(s, tmp, tmp_len); - smart_str_appendc(s, '"'); - - if (*zparam != *((zval **) p)) { - zval_ptr_dtor(zparam); - } - efree(tmp); + append_string: +#if PHP_VERSION_ID < 70300 + str = php_addslashes(tmpstr, 1); +#else + str = php_addslashes(tmpstr); + zend_string_release(tmpstr); +#endif + smart_str_appendc(arg->buffer, '"'); + smart_str_appendl(arg->buffer, str->val, str->len); + smart_str_appendc(arg->buffer, '"'); + zend_string_release(str); break; } } - ++(*i); + ++arg->index; return ZEND_HASH_APPLY_KEEP; } -static void array_param_to_string(zval **zconv, HashTable *ht, char **str, int *len TSRMLS_DC) +static zend_string *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type) { smart_str s = {0}; - unsigned i = 0; + struct apply_to_param_from_array_arg arg = {NULL}; + + switch (type) { +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) +# ifdef PHP_PQ_OID_JSONB + case PHP_PQ_OID_JSONB: +# endif + case PHP_PQ_OID_JSON: + php_json_encode(&s, zarr, PHP_JSON_UNESCAPED_UNICODE); + break; +#endif - smart_str_appendc(&s, '{'); - zend_hash_apply_with_arguments(ht TSRMLS_CC, apply_to_param_from_array, 3, &i, &s, zconv); - smart_str_appendc(&s, '}'); + default: + arg.params = p; + arg.buffer = &s; + arg.type = PHP_PQ_TYPE_OF_ARRAY(type); + arg.delim = PHP_PQ_DELIM_OF_ARRAY(type); + arg.zconv = zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type)); + smart_str_appendc(arg.buffer, '{'); + SEPARATE_ZVAL(zarr); + zend_hash_apply_with_argument(Z_ARRVAL_P(zarr), apply_to_param_from_array, &arg); + smart_str_appendc(arg.buffer, '}'); + break; + } smart_str_0(&s); - *str = s.c; - *len = s.len; + return s.s; } -static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **zp) +static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval *zpp) { - zval **zconv = NULL; + zval *zconv = NULL; Oid type = p->type.count > index ? p->type.oids[index] : 0; - TSRMLS_DF(p); - if (type && SUCCESS == zend_hash_index_find(&p->type.conv, type, (void *) &zconv)) { - zval *rv = NULL; + if (type && (zconv = zend_hash_index_find(&p->type.conv, type))) { + zval ztype, rv; - zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, *zp); - convert_to_string(rv); - p->param.strings[index] = Z_STRVAL_P(rv); - zend_hash_next_index_insert(&p->param.dtor, (void *) &rv, sizeof(zval *), NULL); + ZVAL_NULL(&rv); + ZVAL_LONG(&ztype, type); + zend_call_method_with_2_params(zconv, NULL, NULL, "converttostring", &rv, zpp, &ztype); + convert_to_string(&rv); + p->param.strings[index] = Z_STRVAL_P(&rv); + zend_hash_next_index_insert(&p->param.dtor, &rv); } else { - zval **zpp = zp; + zval tmp; + zend_string *str = NULL; + char tmp_str[64]; + size_t tmp_len = 0; + + again: + switch (Z_TYPE_P(zpp)) { + case IS_REFERENCE: + ZVAL_DEREF(zpp); + goto again; - switch (Z_TYPE_PP(zp)) { case IS_NULL: p->param.strings[index] = NULL; return; - case IS_BOOL: - p->param.strings[index] = Z_BVAL_PP(zp) ? "t" : "f"; + case IS_TRUE: + p->param.strings[index] = "t"; + break; + + case IS_FALSE: + p->param.strings[index] = "f"; return; case IS_DOUBLE: - SEPARATE_ZVAL(zp); - Z_TYPE_PP(zp) = IS_STRING; - Z_STRLEN_PP(zp) = spprintf(&Z_STRVAL_PP(zp), 0, "%F", Z_DVAL_PP((zval **)p)); + tmp_len = slprintf(tmp_str, sizeof(tmp_str), "%F", Z_DVAL_P(zpp)); + str = zend_string_init(tmp_str, tmp_len, 0); break; case IS_ARRAY: - { - -#if HAVE_PHP_PQ_TYPE_H -# undef PHP_PQ_TYPE -# include "php_pq_type.h" -#else -# define PHP_PQ_TYPE_OF_ARRAY(oid) 0 -#endif - - zval *tmp; - MAKE_STD_ZVAL(tmp); - Z_TYPE_P(tmp) = IS_STRING; - zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type), (void *) &zconv); - array_param_to_string(zconv, Z_ARRVAL_PP(zp), &Z_STRVAL_P(tmp), &Z_STRLEN_P(tmp) TSRMLS_CC); - zp = &tmp; + str = array_param_to_string(p, zpp, type); break; - } + case IS_OBJECT: + if ((str = object_param_to_string(p, zpp, type))) { + break; + } + /* no break */ default: - convert_to_string_ex(zp); + str = zval_get_string(zpp); break; } - p->param.strings[index] = Z_STRVAL_PP(zp); - - if (*zp != *zpp) { - zend_hash_next_index_insert(&p->param.dtor, zp, sizeof(zval *), NULL); + if (str) { + ZVAL_STR(&tmp, str); + p->param.strings[index] = Z_STRVAL(tmp); + zend_hash_next_index_insert(&p->param.dtor, &tmp); } } } -static int apply_to_params(void *zp TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +struct apply_to_params_arg { + php_pq_params_t *params; + unsigned index; +}; + +static int apply_to_params(zval *zp, void *arg_ptr) { - php_pq_params_t *p = (php_pq_params_t *) va_arg(argv, php_pq_params_t *); - unsigned *index = (unsigned *) va_arg(argv, unsigned *); + struct apply_to_params_arg *arg = arg_ptr; - php_pq_params_set_param(p, (*index)++, zp); + SEPARATE_ZVAL_IF_NOT_REF(zp); + php_pq_params_set_param(arg->params, arg->index++, zp); return ZEND_HASH_APPLY_KEEP; } unsigned php_pq_params_add_param(php_pq_params_t *p, zval *param) { p->param.strings = safe_erealloc(p->param.strings, ++p->param.count, sizeof(*p->param.strings), 0); - php_pq_params_set_param(p, p->param.count-1, ¶m); + php_pq_params_set_param(p, p->param.count-1, param); return p->type.count; } unsigned php_pq_params_set_params(php_pq_params_t *p, HashTable *params) { p->param.count = params ? zend_hash_num_elements(params) : 0; - TSRMLS_DF(p); if (p->param.strings) { efree(p->param.strings); @@ -249,9 +329,9 @@ unsigned php_pq_params_set_params(php_pq_params_t *p, HashTable *params) } zend_hash_clean(&p->param.dtor); if (p->param.count) { - unsigned index = 0; + struct apply_to_params_arg arg = {p, 0}; p->param.strings = ecalloc(p->param.count, sizeof(*p->param.strings)); - zend_hash_apply_with_arguments(params TSRMLS_CC, apply_to_params, 2, p, &index); + zend_hash_apply_with_argument(params, apply_to_params, &arg); } return p->param.count; } @@ -270,11 +350,10 @@ void php_pq_params_free(php_pq_params_t **p) } } -php_pq_params_t *php_pq_params_init(HashTable *conv, HashTable *oids, HashTable *params TSRMLS_DC) +php_pq_params_t *php_pq_params_init(HashTable *conv, HashTable *oids, HashTable *params) { php_pq_params_t *p = ecalloc(1, sizeof(*p)); - TSRMLS_CF(p); zend_hash_init(&p->type.conv, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&p->param.dtor, 0, NULL, ZVAL_PTR_DTOR, 0);