ZEND_END_ARG_INFO();
static PHP_METHOD(pqdt, __toString)
{
- zval *rv;
+ zval *rv = NULL;
zend_call_method_with_1_params(&getThis(), php_pqdt_class_entry, NULL, "format", &rv,
zend_read_property(php_pqdt_class_entry, getThis(), ZEND_STRL("format"), 0 TSRMLS_CC));
- RETVAL_ZVAL(rv, 1, 1);
+ if (rv) {
+ RETVAL_ZVAL(rv, 1, 1);
+ }
}
static zend_function_entry php_pqdt_methods[] = {
return zv;
}
+void php_pqdt_to_string(zval *zdt, const char *format, char **str_buf, size_t *str_len TSRMLS_DC)
+{
+ zval rv;
+
+ INIT_PZVAL(&rv);
+ ZVAL_NULL(&rv);
+
+ if (Z_OBJ_HT_P(zdt)->cast_object
+ && SUCCESS == Z_OBJ_HT_P(zdt)->cast_object(zdt, &rv, IS_STRING TSRMLS_CC)
+ ) {
+ *str_len = Z_STRLEN(rv);
+ *str_buf = Z_STRVAL(rv);
+ } else if (instanceof_function(Z_OBJCE_P(zdt), php_date_get_date_ce() TSRMLS_CC)) {
+ zval *rv = NULL, *zfmt;
+
+ MAKE_STD_ZVAL(zfmt);
+ ZVAL_STRING(zfmt, format, 1);
+ zend_call_method_with_1_params(&zdt, Z_OBJCE_P(zdt), NULL, "format", &rv, zfmt);
+ zval_ptr_dtor(&zfmt);
+
+ if (rv) {
+ if (Z_TYPE_P(rv) == IS_STRING) {
+ *str_len = Z_STRLEN_P(rv);
+ *str_buf = estrndup(Z_STRVAL_P(rv), *str_len);
+ }
+ zval_ptr_dtor(&rv);
+ }
+ }
+}
+
zend_class_entry *php_pqconv_class_entry;
ZEND_BEGIN_ARG_INFO_EX(ai_pqconv_convert_types, 0, 0, 0)
INIT_NS_CLASS_ENTRY(ce ,"pq", "DateTime", php_pqdt_methods);
php_pqdt_class_entry = zend_register_internal_class_ex(&ce, php_date_get_date_ce(), "DateTime" TSRMLS_CC);
- zend_declare_property_stringl(php_pqdt_class_entry, ZEND_STRL("format"), ZEND_STRL("Y-m-d H:i:s.u"), ZEND_ACC_PUBLIC TSRMLS_CC);
+ zend_declare_property_stringl(php_pqdt_class_entry, ZEND_STRL("format"), ZEND_STRL("Y-m-d H:i:s.uO"), ZEND_ACC_PUBLIC TSRMLS_CC);
/* stop reading this file right here! */
if (SUCCESS == zend_hash_find(CG(class_table), ZEND_STRS("jsonserializable"), (void *) &json)) {
#include <php.h>
#include <ext/standard/php_string.h>
#include <ext/standard/php_smart_str.h>
+#include <ext/json/php_json.h>
#include <Zend/zend_interfaces.h>
#include "php_pq.h"
#include "php_pq_params.h"
+#include "php_pq_misc.h"
#undef PHP_PQ_TYPE
#include "php_pq_type.h"
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 zval *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type TSRMLS_DC)
+{
+ zval *return_value = NULL;
+ smart_str str = {0};
+
+ switch (type) {
+#ifdef PHP_PQ_OID_JSON
+# ifdef PHP_PQ_OID_JSONB
+ case PHP_PQ_OID_JSONB:
+# endif
+ case PHP_PQ_OID_JSON:
+ php_json_encode(&str, zobj, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC);
+ smart_str_0(&str);
+ break;
+#endif
+
+ case PHP_PQ_OID_DATE:
+ php_pqdt_to_string(zobj, "Y-m-d", &str.c, &str.len TSRMLS_CC);
+ break;
+
+ case PHP_PQ_OID_ABSTIME:
+ php_pqdt_to_string(zobj, "Y-m-d H:i:s", &str.c, &str.len TSRMLS_CC);
+ break;
+
+ case PHP_PQ_OID_TIMESTAMP:
+ php_pqdt_to_string(zobj, "Y-m-d H:i:s.u", &str.c, &str.len TSRMLS_CC);
+ break;
+
+ case PHP_PQ_OID_TIMESTAMPTZ:
+ php_pqdt_to_string(zobj, "Y-m-d H:i:s.uO", &str.c, &str.len TSRMLS_CC);
+ break;
+
+ default:
+ SEPARATE_ZVAL(&zobj);
+ convert_to_string(zobj);
+ return_value = zobj;
+ break;
+ }
+
+ if (str.c) {
+ MAKE_STD_ZVAL(return_value);
+ RETVAL_STRINGL(str.c, str.len, 0);
+ }
+
+ return return_value;
+}
+
+static int apply_to_param_from_array(void *ptr TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
{
- zval **zparam = p;
+ php_pq_params_t *p = va_arg(argv, php_pq_params_t *);
unsigned j, *i = va_arg(argv, unsigned *);
smart_str *s = va_arg(argv, smart_str *);
- zval **zconv = va_arg(argv, zval **);
+ Oid type = va_arg(argv, Oid);
+ zval *ztmp, **zparam = ptr, *zcopy = *zparam, **zconv = va_arg(argv, zval **);
char *tmp;
size_t len;
int tmp_len;
if (zconv) {
zval *rv = NULL;
- zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, *zparam);
+ zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, zcopy);
convert_to_string(rv);
- smart_str_appendl(s, Z_STRVAL_P(rv), Z_STRLEN_P(rv));
- zval_ptr_dtor(&rv);
+ zcopy = rv;
+ goto append_string;
} else {
- switch (Z_TYPE_PP(zparam)) {
+ switch (Z_TYPE_P(zcopy)) {
case IS_NULL:
smart_str_appends(s, "NULL");
break;
case IS_BOOL:
- smart_str_appends(s, Z_BVAL_PP(zparam) ? "t" : "f");
+ smart_str_appends(s, Z_BVAL_P(zcopy) ? "t" : "f");
break;
case IS_LONG:
- smart_str_append_long(s, Z_LVAL_PP(zparam));
+ smart_str_append_long(s, Z_LVAL_P(zcopy));
break;
case IS_DOUBLE:
- len = spprintf(&tmp, 0, "%F", Z_DVAL_PP(zparam));
+ len = spprintf(&tmp, 0, "%F", Z_DVAL_P(zcopy));
smart_str_appendl(s, 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);
+ zend_hash_apply_with_arguments(Z_ARRVAL_P(zcopy) TSRMLS_CC, apply_to_param_from_array, 5, p, &j, s, type, zconv);
smart_str_appendc(s, '}');
break;
- default:
- SEPARATE_ZVAL(zparam);
- if (Z_TYPE_PP(zparam) != IS_STRING) {
- convert_to_string(*zparam);
+ case IS_OBJECT:
+ if ((ztmp = object_param_to_string(p, zcopy, type TSRMLS_CC))) {
+ zcopy = ztmp;
}
+ /* no break */
+ default:
+ SEPARATE_ZVAL(&zcopy);
+ convert_to_string(zcopy);
- tmp = php_addslashes(Z_STRVAL_PP(zparam), Z_STRLEN_PP(zparam), &tmp_len, 0 TSRMLS_CC);
+ append_string:
+ tmp = php_addslashes(Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy), &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);
+ if (zcopy != *zparam) {
+ zval_ptr_dtor(&zcopy);
}
efree(tmp);
break;
return ZEND_HASH_APPLY_KEEP;
}
-static void array_param_to_string(zval **zconv, HashTable *ht, char **str, int *len TSRMLS_DC)
+static zval *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type TSRMLS_DC)
{
+ zval *return_value, **zconv = NULL;
smart_str s = {0};
unsigned i = 0;
- 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, '}');
+ switch (type) {
+#ifdef 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 TSRMLS_CC);
+ smart_str_0(&s);
+ break;
+#endif
+
+ default:
+ zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type), (void *) &zconv);
+
+ smart_str_appendc(&s, '{');
+ 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);
+ smart_str_appendc(&s, '}');
+ smart_str_0(&s);
+ break;
+ }
+
+ /* must not return NULL */
+ MAKE_STD_ZVAL(return_value);
- smart_str_0(&s);
- *str = s.c;
- *len = s.len;
+ if (s.c) {
+ RETVAL_STRINGL(s.c, s.len, 0);
+ } else {
+ RETVAL_EMPTY_STRING();
+ }
+
+ return return_value;
}
-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;
Oid type = p->type.count > index ? p->type.oids[index] : 0;
if (type && SUCCESS == zend_hash_index_find(&p->type.conv, type, (void *) &zconv)) {
zval *rv = NULL;
- zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, *zp);
+ zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, *zpp);
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);
} else {
- zval **zpp = zp;
+ zval *tmp, *zcopy = *zpp;
- switch (Z_TYPE_PP(zp)) {
+ switch (Z_TYPE_P(zcopy)) {
case IS_NULL:
p->param.strings[index] = NULL;
return;
case IS_BOOL:
- p->param.strings[index] = Z_BVAL_PP(zp) ? "t" : "f";
+ p->param.strings[index] = Z_BVAL_P(zcopy) ? "t" : "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(zpp));
+ SEPARATE_ZVAL(&zcopy);
+ Z_TYPE_P(zcopy) = IS_STRING;
+ Z_STRLEN_P(zcopy) = spprintf(&Z_STRVAL_P(zcopy), 0, "%F", Z_DVAL_PP(zpp));
break;
case IS_ARRAY:
- {
- 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;
+ zcopy = array_param_to_string(p, zcopy, type TSRMLS_CC);
break;
- }
+
+ case IS_OBJECT:
+ if ((tmp = object_param_to_string(p, zcopy, type TSRMLS_CC))) {
+ zcopy = tmp;
+ break;
+ }
+ /* no break */
default:
- convert_to_string_ex(zp);
+ convert_to_string_ex(&zcopy);
break;
}
- p->param.strings[index] = Z_STRVAL_PP(zp);
+ p->param.strings[index] = Z_STRVAL_P(zcopy);
- if (*zp != *zpp) {
- zend_hash_next_index_insert(&p->param.dtor, zp, sizeof(zval *), NULL);
+ if (zcopy != *zpp) {
+ zend_hash_next_index_insert(&p->param.dtor, (void *) &zcopy, sizeof(zval *), NULL);
}
}
}
<?php
include "_skipif.inc";
?>
+--INI--
+date.timezone=UTC
--FILE--
<?php
echo "Test\n";
}
}
+class Text {
+ private $data;
+ function __construct($data) {
+ $this->data = $data;
+ }
+ function __toString() {
+ return (string) $this->data;
+ }
+}
+
$c = new pq\Connection(PQ_DSN);
$c->exec("CREATE EXTENSION IF NOT EXISTS hstore");
$t = new pq\Types($c);
$c->setConverter(new HStoreConverter($t));
$c->setConverter(new IntVectorConverter($t));
-$c->setConverter(new JSONConverter($t));
-
-$r = $c->execParams("SELECT \$1 as hs, \$2 as iv, \$3 as oids, \$4 as js, \$5 as ia, \$6 as ta, \$7 as ba, \$8 as da",
+if (!defined("pq\\Types::JSON")) {
+ $c->setConverter(new JSONConverter($t));
+}
+$r = $c->execParams("SELECT \$1 as hs, \$2 as iv, \$3 as oids, \$4 as js, \$5 as ia, \$6 as ta, \$7 as ba, \$8 as da, \$9 as dbl, \$10 as bln, ".
+ "\$11 as dt1, \$12 as dt2, \$13 as dt3, \$14 as dt4, \$15 as dt5, \$16 as dt6, \$17 as dt7, \$18 as dt8, \$19 as txta ",
array(
// hstore
array(
array(array(array(1,2,3))),
array(array("a\"","b}",null)),
array(true,false),
- array(1.1,2.2)
+ array(1.1,2.2),
+ // double
+ 123.456,
+ // bool
+ true,
+ // datetimes
+ new pq\Datetime,
+ new pq\Datetime,
+ new pq\Datetime,
+ new pq\Datetime,
+ new pq\Datetime,
+ new pq\Datetime,
+ new pq\Datetime,
+ new pq\Datetime,
+ [new Text(0), new Text(" or "), new Text(true)],
),
array(
$t["hstore"]->oid,
$t["_int4"]->oid,
$t["_text"]->oid,
$t["_bool"]->oid,
- $t["_float8"]->oid
+ $t["_float8"]->oid,
+ $t["float4"]->oid,
+ $t["bool"]->oid,
+ $t["date"]->oid,
+ $t["abstime"]->oid,
+ $t["timestamp"]->oid,
+ $t["timestamptz"]->oid,
+ $t["date"]->oid,
+ $t["abstime"]->oid,
+ $t["timestamp"]->oid,
+ $t["timestamptz"]->oid,
+ $t["_text"]->oid
)
);
[1]=>
float(2.2)
}
+ [8]=>
+ float(123.456)
+ [9]=>
+ bool(true)
+ [10]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(5) "Y-m-d"
+ ["date"]=>
+ string(26) "%d-%d-%d 00:00:00.000000"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ [11]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(11) "Y-m-d H:i:s"
+ ["date"]=>
+ string(26) "%d-%d-%d %d:%d:%d.000000"
+ ["timezone_type"]=>
+ int(1)
+ ["timezone"]=>
+ string(%d) "%s"
+ }
+ [12]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(13) "Y-m-d H:i:s.u"
+ ["date"]=>
+ string(26) "%d-%d-%d %d:%d:%d.000000"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ [13]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(14) "Y-m-d H:i:s.uO"
+ ["date"]=>
+ string(26) "%d-%d-%d %d:%d:%d.000000"
+ ["timezone_type"]=>
+ int(1)
+ ["timezone"]=>
+ string(%d) "%s"
+ }
+ [14]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(5) "Y-m-d"
+ ["date"]=>
+ string(26) "%d-%d-%d 00:00:00.000000"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ [15]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(11) "Y-m-d H:i:s"
+ ["date"]=>
+ string(26) "%d-%d-%d %d:%d:%d.000000"
+ ["timezone_type"]=>
+ int(1)
+ ["timezone"]=>
+ string(%d) "%s"
+ }
+ [16]=>
+ object(pq\DateTime)#%d (4) {
+ ["format"]=>
+ string(13) "Y-m-d H:i:s.u"
+ ["date"]=>
+ string(26) "%d-%d-%d %d:%d:%d.000000"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+ }
+ [17]=>
+ object(pq\DateTime)#159 (4) {
+ ["format"]=>
+ string(14) "Y-m-d H:i:s.uO"
+ ["date"]=>
+ string(26) "%d-%d-%d %d:%d:%d.000000"
+ ["timezone_type"]=>
+ int(1)
+ ["timezone"]=>
+ string(%d) "%s"
+ }
+ [18]=>
+ array(3) {
+ [0]=>
+ string(1) "0"
+ [1]=>
+ string(4) " or "
+ [2]=>
+ string(1) "1"
+ }
}
}
Done