From: Michael Wallner Date: Fri, 22 May 2015 10:31:21 +0000 (+0200) Subject: Fixed array parser compatibility with arrays of boxes X-Git-Tag: v0.6.0RC1~8 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=commitdiff_plain;h=d3fbce1b02b41d7ee1f3d0b60dc8df411aae7d79 Fixed array parser compatibility with arrays of boxes --- diff --git a/TODO b/TODO index be41c6c..4f7fadb 100644 --- a/TODO +++ b/TODO @@ -3,4 +3,3 @@ * fetchInto/fetchCtor? * binary protocol? * parse explicit array dimension information in front of arrays -* compat for box arrays diff --git a/package.xml b/package.xml index d1a8715..ea94c6c 100644 --- a/package.xml +++ b/package.xml @@ -49,6 +49,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> BSD, revised diff --git a/php_pq_type.awk b/php_pq_type.awk index 15ffd1b..b5d07b4 100755 --- a/php_pq_type.awk +++ b/php_pq_type.awk @@ -13,22 +13,32 @@ END { printf "\t||\t((oid) == %d) \\\n", oid } printf ")\n#endif\n" + printf "#ifndef PHP_PQ_TYPE_OF_ARRAY\n" printf "# define PHP_PQ_TYPE_OF_ARRAY(oid) (" for (oid in arrays) { printf "\\\n\t(oid) == %d ? %s : ", oid, arrays[oid] } printf "0 \\\n)\n#endif\n" + + printf "#ifndef PHP_PQ_DELIM_OF_ARRAY\n" + printf "# define PHP_PQ_DELIM_OF_ARRAY(oid) (" + for (oid in delims) { + printf "\\\n\t(oid) == %d ? '%s' : ", oid, delims[oid] + } + printf "0 \\\n)\n#endif\n" } /^DATA/ { oid = $4 name = toupper($6) + adelim = $15 atypoid = $17 if (sub("^_", "", name)) { arrays[oid] = atypoid name = name "ARRAY" } + delims[oid] = adelim printf "#ifndef PHP_PQ_OID_%s\n", name printf "# define PHP_PQ_OID_%s %d\n", name, oid printf "#endif\n" diff --git a/php_pq_type.h b/php_pq_type.h index e0fd421..a1b3735 100644 --- a/php_pq_type.h +++ b/php_pq_type.h @@ -770,3 +770,163 @@ PHP_PQ_TYPE("ANYRANGE", 3831) (oid) == 3927 ? 3926 : 0 \ ) #endif +#ifndef PHP_PQ_DELIM_OF_ARRAY +# define PHP_PQ_DELIM_OF_ARRAY(oid) (\ + (oid) == 16 ? '\054' : \ + (oid) == 17 ? '\054' : \ + (oid) == 18 ? '\054' : \ + (oid) == 19 ? '\054' : \ + (oid) == 20 ? '\054' : \ + (oid) == 21 ? '\054' : \ + (oid) == 22 ? '\054' : \ + (oid) == 23 ? '\054' : \ + (oid) == 24 ? '\054' : \ + (oid) == 25 ? '\054' : \ + (oid) == 26 ? '\054' : \ + (oid) == 27 ? '\054' : \ + (oid) == 28 ? '\054' : \ + (oid) == 29 ? '\054' : \ + (oid) == 30 ? '\054' : \ + (oid) == 71 ? '\054' : \ + (oid) == 75 ? '\054' : \ + (oid) == 81 ? '\054' : \ + (oid) == 83 ? '\054' : \ + (oid) == 114 ? '\054' : \ + (oid) == 142 ? '\054' : \ + (oid) == 143 ? '\054' : \ + (oid) == 194 ? '\054' : \ + (oid) == 199 ? '\054' : \ + (oid) == 210 ? '\054' : \ + (oid) == 600 ? '\054' : \ + (oid) == 601 ? '\054' : \ + (oid) == 602 ? '\054' : \ + (oid) == 603 ? '\073' : \ + (oid) == 604 ? '\054' : \ + (oid) == 628 ? '\054' : \ + (oid) == 629 ? '\054' : \ + (oid) == 650 ? '\054' : \ + (oid) == 651 ? '\054' : \ + (oid) == 700 ? '\054' : \ + (oid) == 701 ? '\054' : \ + (oid) == 702 ? '\054' : \ + (oid) == 703 ? '\054' : \ + (oid) == 704 ? '\054' : \ + (oid) == 705 ? '\054' : \ + (oid) == 718 ? '\054' : \ + (oid) == 719 ? '\054' : \ + (oid) == 790 ? '\054' : \ + (oid) == 791 ? '\054' : \ + (oid) == 829 ? '\054' : \ + (oid) == 869 ? '\054' : \ + (oid) == 1000 ? '\054' : \ + (oid) == 1001 ? '\054' : \ + (oid) == 1002 ? '\054' : \ + (oid) == 1003 ? '\054' : \ + (oid) == 1005 ? '\054' : \ + (oid) == 1006 ? '\054' : \ + (oid) == 1007 ? '\054' : \ + (oid) == 1008 ? '\054' : \ + (oid) == 1009 ? '\054' : \ + (oid) == 1010 ? '\054' : \ + (oid) == 1011 ? '\054' : \ + (oid) == 1012 ? '\054' : \ + (oid) == 1013 ? '\054' : \ + (oid) == 1014 ? '\054' : \ + (oid) == 1015 ? '\054' : \ + (oid) == 1016 ? '\054' : \ + (oid) == 1017 ? '\054' : \ + (oid) == 1018 ? '\054' : \ + (oid) == 1019 ? '\054' : \ + (oid) == 1020 ? '\073' : \ + (oid) == 1021 ? '\054' : \ + (oid) == 1022 ? '\054' : \ + (oid) == 1023 ? '\054' : \ + (oid) == 1024 ? '\054' : \ + (oid) == 1025 ? '\054' : \ + (oid) == 1027 ? '\054' : \ + (oid) == 1028 ? '\054' : \ + (oid) == 1033 ? '\054' : \ + (oid) == 1034 ? '\054' : \ + (oid) == 1040 ? '\054' : \ + (oid) == 1041 ? '\054' : \ + (oid) == 1042 ? '\054' : \ + (oid) == 1043 ? '\054' : \ + (oid) == 1082 ? '\054' : \ + (oid) == 1083 ? '\054' : \ + (oid) == 1114 ? '\054' : \ + (oid) == 1115 ? '\054' : \ + (oid) == 1182 ? '\054' : \ + (oid) == 1183 ? '\054' : \ + (oid) == 1184 ? '\054' : \ + (oid) == 1185 ? '\054' : \ + (oid) == 1186 ? '\054' : \ + (oid) == 1187 ? '\054' : \ + (oid) == 1231 ? '\054' : \ + (oid) == 1263 ? '\054' : \ + (oid) == 1266 ? '\054' : \ + (oid) == 1270 ? '\054' : \ + (oid) == 1560 ? '\054' : \ + (oid) == 1561 ? '\054' : \ + (oid) == 1562 ? '\054' : \ + (oid) == 1563 ? '\054' : \ + (oid) == 1700 ? '\054' : \ + (oid) == 1790 ? '\054' : \ + (oid) == 2201 ? '\054' : \ + (oid) == 2202 ? '\054' : \ + (oid) == 2203 ? '\054' : \ + (oid) == 2204 ? '\054' : \ + (oid) == 2205 ? '\054' : \ + (oid) == 2206 ? '\054' : \ + (oid) == 2207 ? '\054' : \ + (oid) == 2208 ? '\054' : \ + (oid) == 2209 ? '\054' : \ + (oid) == 2210 ? '\054' : \ + (oid) == 2211 ? '\054' : \ + (oid) == 2249 ? '\054' : \ + (oid) == 2275 ? '\054' : \ + (oid) == 2276 ? '\054' : \ + (oid) == 2277 ? '\054' : \ + (oid) == 2278 ? '\054' : \ + (oid) == 2279 ? '\054' : \ + (oid) == 2280 ? '\054' : \ + (oid) == 2281 ? '\054' : \ + (oid) == 2282 ? '\054' : \ + (oid) == 2283 ? '\054' : \ + (oid) == 2287 ? '\054' : \ + (oid) == 2776 ? '\054' : \ + (oid) == 2949 ? '\054' : \ + (oid) == 2950 ? '\054' : \ + (oid) == 2951 ? '\054' : \ + (oid) == 2970 ? '\054' : \ + (oid) == 3115 ? '\054' : \ + (oid) == 3220 ? '\054' : \ + (oid) == 3221 ? '\054' : \ + (oid) == 3500 ? '\054' : \ + (oid) == 3614 ? '\054' : \ + (oid) == 3615 ? '\054' : \ + (oid) == 3642 ? '\054' : \ + (oid) == 3643 ? '\054' : \ + (oid) == 3644 ? '\054' : \ + (oid) == 3645 ? '\054' : \ + (oid) == 3734 ? '\054' : \ + (oid) == 3735 ? '\054' : \ + (oid) == 3769 ? '\054' : \ + (oid) == 3770 ? '\054' : \ + (oid) == 3802 ? '\054' : \ + (oid) == 3807 ? '\054' : \ + (oid) == 3831 ? '\054' : \ + (oid) == 3838 ? '\054' : \ + (oid) == 3904 ? '\054' : \ + (oid) == 3905 ? '\054' : \ + (oid) == 3906 ? '\054' : \ + (oid) == 3907 ? '\054' : \ + (oid) == 3908 ? '\054' : \ + (oid) == 3909 ? '\054' : \ + (oid) == 3910 ? '\054' : \ + (oid) == 3911 ? '\054' : \ + (oid) == 3912 ? '\054' : \ + (oid) == 3913 ? '\054' : \ + (oid) == 3926 ? '\054' : \ + (oid) == 3927 ? '\054' : 0 \ +) +#endif diff --git a/src/php_pq_misc.c b/src/php_pq_misc.c index af36c33..a3db8bb 100644 --- a/src/php_pq_misc.c +++ b/src/php_pq_misc.c @@ -25,6 +25,8 @@ #include "php_pq.h" #include "php_pqexc.h" #include "php_pq_misc.h" +#undef PHP_PQ_TYPE +#include "php_pq_type.h" char *php_pq_rtrim(char *e) { @@ -267,7 +269,7 @@ static ZEND_RESULT_CODE add_element(ArrayParserState *a, const char *start) static ZEND_RESULT_CODE parse_array(ArrayParserState *a); -static ZEND_RESULT_CODE parse_element(ArrayParserState *a) +static ZEND_RESULT_CODE parse_element(ArrayParserState *a, char delim) { const char *el; TSRMLS_FETCH_FROM_CTX(a->ts); @@ -284,6 +286,10 @@ static ZEND_RESULT_CODE parse_element(ArrayParserState *a) for (el = a->ptr; a->ptr < a->end; ++a->ptr) { switch (*a->ptr) { + case '\\': + a->escaped = !a->escaped; + break; + case '"': if (a->escaped) { a->escaped = 0; @@ -300,20 +306,18 @@ static ZEND_RESULT_CODE parse_element(ArrayParserState *a) } break; - case ',': + default: + if (delim != *a->ptr) { + a->escaped = 0; + break; + } + /* no break */ case '}': if (!a->quotes) { return add_element(a, el); } break; - case '\\': - a->escaped = !a->escaped; - break; - - default: - a->escaped = 0; - break; } } @@ -323,10 +327,11 @@ static ZEND_RESULT_CODE parse_element(ArrayParserState *a) static ZEND_RESULT_CODE parse_elements(ArrayParserState *a) { + char delims[] = {'}', PHP_PQ_DELIM_OF_ARRAY(a->typ), 0}; TSRMLS_FETCH_FROM_CTX(a->ts); - while (SUCCESS == parse_element(a)) { - switch (caa(a, ",}", 0)) { + while (SUCCESS == parse_element(a, delims[1])) { + switch (caa(a, delims, 0)) { case 0: return FAILURE; diff --git a/src/php_pq_params.c b/src/php_pq_params.c index 9554ef7..1ae7dd6 100644 --- a/src/php_pq_params.c +++ b/src/php_pq_params.c @@ -134,6 +134,7 @@ struct apply_to_param_from_array_arg { unsigned index; smart_str *buffer; Oid type; + char delim; zval **zconv; }; @@ -146,7 +147,7 @@ static int apply_to_param_from_array(void *ptr, void *arg_ptr TSRMLS_DC) int tmp_len; if (arg->index++) { - smart_str_appendc(arg->buffer, ','); + smart_str_appendc(arg->buffer, arg->delim); } if (arg->zconv) { @@ -241,6 +242,7 @@ static zval *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type TSRM arg.params = p; arg.buffer = &s; arg.type = PHP_PQ_TYPE_OF_ARRAY(type); + arg.delim = PHP_PQ_DELIM_OF_ARRAY(type); zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type), (void *) &arg.zconv); smart_str_appendc(arg.buffer, '{'); MAKE_STD_ZVAL(zcopy); diff --git a/tests/conv001.phpt b/tests/conv001.phpt index 6e794aa..64488b5 100644 --- a/tests/conv001.phpt +++ b/tests/conv001.phpt @@ -78,6 +78,43 @@ class JSONConverter extends Converter } } +class Point { + public $x; + public $y; + function __construct($x, $y) { + $this->x = $x; + $this->y = $y; + } +} + +class Box { + public $p1; + public $p2; + function __construct(Point $p1, Point $p2) { + $this->p1 = $p1; + $this->p2 = $p2; + } +} + +class BoxConverter extends Converter +{ + function convertTypes() { + return [ $this->types["box"]->oid ]; + } + + function convertToString($box, $type) { + return sprintf("(%F,%F),(%F,%F)", + $box->p1->x, $box->p1->y, + $box->p2->x, $box->p2->y + ); + } + + function convertFromString($data, $type) { + list($p1x, $p1y, $p2x, $p2y) = sscanf($data, "(%f,%f),(%f,%f)"); + return new Box(new Point($p1x, $p1y), new Point($p2x, $p2y)); + } +} + class Text { private $data; function __construct($data) { @@ -97,8 +134,10 @@ $c->setConverter(new IntVectorConverter($t)); if (!defined("pq\\Types::JSON")) { $c->setConverter(new JSONConverter($t)); } +$c->setConverter(new BoxConverter($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 ", + "\$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, \$20 as boxa", array( // hstore array( @@ -141,7 +180,10 @@ $r = $c->execParams("SELECT \$1 as hs, \$2 as iv, \$3 as oids, \$4 as js, \$5 as new pq\Datetime, new pq\Datetime, new pq\Datetime, + // text array [new Text(0), new Text(" or "), new Text(true)], + // box array + [new Box(new Point(1,2), new Point(2,3)), new Box(new Point(3,4), new Point(4,5))], ), array( $t["hstore"]->oid, @@ -162,7 +204,8 @@ $r = $c->execParams("SELECT \$1 as hs, \$2 as iv, \$3 as oids, \$4 as js, \$5 as $t["abstime"]->oid, $t["timestamp"]->oid, $t["timestamptz"]->oid, - $t["_text"]->oid + $t["_text"]->oid, + $t["_box"]->oid ) ); @@ -366,6 +409,43 @@ array(1) { [2]=> string(1) "1" } + [19]=> + array(2) { + [0]=> + object(Box)#%d (2) { + ["p1"]=> + object(Point)#%d (2) { + ["x"]=> + float(2) + ["y"]=> + float(3) + } + ["p2"]=> + object(Point)#%d (2) { + ["x"]=> + float(1) + ["y"]=> + float(2) + } + } + [1]=> + object(Box)#%d (2) { + ["p1"]=> + object(Point)#%d (2) { + ["x"]=> + float(4) + ["y"]=> + float(5) + } + ["p2"]=> + object(Point)#%d (2) { + ["x"]=> + float(3) + ["y"]=> + float(4) + } + } + } } } Done diff --git a/tests/types002.phpt b/tests/types002.phpt index 431ee3e..7122cf1 100644 --- a/tests/types002.phpt +++ b/tests/types002.phpt @@ -25,14 +25,15 @@ true as bool, 1::abstime as abstime, '2013-01-01 01:01:01'::timestamp as timestamp, '2013-01-01 01:01:01 UTC'::timestamptz as timestamptz, -array[array[1,2,3],array[4,5,6],array[NULL::int,NULL::int,NULL::int]] as intarray +array[array[1,2,3],array[4,5,6],array[NULL::int,NULL::int,NULL::int]] as intarray, +array[box(point(1,2),point(2,3)),box(point(4,5),point(5,6))] as boxarray "); var_dump($r->fetchRow(pq\Result::FETCH_ASSOC)); ?> DONE --EXPECTF-- Test -array(12) { +array(13) { ["null"]=> NULL ["bool"]=> @@ -121,5 +122,12 @@ array(12) { NULL } } + ["boxarray"]=> + array(2) { + [0]=> + string(11) "(2,3),(1,2)" + [1]=> + string(11) "(5,6),(4,5)" + } } DONE \ No newline at end of file