From 9579761f9d426395914c2cc276f8d639cdf81832 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 5 Sep 2014 15:30:01 +0200 Subject: [PATCH] yaz_cql_parse does CQL to RPN (and the reverse) --- php_yaz.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++ php_yaz.h | 2 + tests/connect.phpt | 20 ++++++++ tests/cql.phpt | 51 ++++++++++++++++++++ tests/database.phpt | 21 ++++++++ tests/record.phpt | 63 ++++++++++++++++++++++++ 6 files changed, 290 insertions(+) create mode 100644 tests/connect.phpt create mode 100644 tests/cql.phpt create mode 100644 tests/database.phpt create mode 100644 tests/record.phpt diff --git a/php_yaz.c b/php_yaz.c index 0964cbd..9258365 100644 --- a/php_yaz.c +++ b/php_yaz.c @@ -45,8 +45,10 @@ #include #include #include +#include #include #include +#include #ifndef ODR_INT_PRINTF #define ODR_INT_PRINTF "%d" @@ -58,6 +60,7 @@ typedef struct Yaz_AssociationInfo *Yaz_Association; struct Yaz_AssociationInfo { CCL_bibset bibset; + cql_transform_t ct; ZOOM_connection zoom_conn; ZOOM_resultset zoom_set; ZOOM_scanset zoom_scan; @@ -85,6 +88,7 @@ static Yaz_Association yaz_association_mk() p->order = 0; p->persistent = 0; p->bibset = ccl_qual_mk(); + p->ct = cql_transform_create(); p->time_stamp = 0; return p; } @@ -95,6 +99,7 @@ static void yaz_association_destroy(Yaz_Association p) return; } + cql_transform_close(p->ct); ZOOM_resultset_destroy(p->zoom_set); ZOOM_scanset_destroy(p->zoom_scan); ZOOM_package_destroy(p->zoom_package); @@ -163,6 +168,8 @@ zend_function_entry yaz_functions [] = { PHP_FE(yaz_present, NULL) PHP_FE(yaz_ccl_conf, NULL) PHP_FE(yaz_ccl_parse, third_argument_force_ref) + PHP_FE(yaz_cql_parse, third_argument_force_ref) + PHP_FE(yaz_cql_conf, NULL) PHP_FE(yaz_database, NULL) PHP_FE(yaz_sort, NULL) PHP_FE(yaz_schema, NULL) @@ -1933,6 +1940,132 @@ PHP_FUNCTION(yaz_ccl_parse) } /* }}} */ + +/* {{{ proto bool yaz_cql_parse(resource id, string cql, array res, bool rev) + Parse a CQL query */ +PHP_FUNCTION(yaz_cql_parse) +{ + zval *pval_id, *pval_res = 0; + char *query; + int query_len; + Yaz_Association p; + zend_bool reverse = 0; + + if (ZEND_NUM_ARGS() != 4 || + zend_parse_parameters(4 TSRMLS_CC, "zszb", + &pval_id, &query, &query_len, &pval_res, &reverse) + == FAILURE) { + WRONG_PARAM_COUNT; + } + + zval_dtor(pval_res); + array_init(pval_res); + get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); + if (p) { + if (reverse) { + ODR odr = odr_createmem(ODR_ENCODE); + YAZ_PQF_Parser pp = yaz_pqf_create(); + Z_RPNQuery *rpn = yaz_pqf_parse(pp, odr, query); + WRBUF wrbuf_cql = wrbuf_alloc(); + int r; + if (!rpn) { + add_assoc_long(pval_res, "errorcode", 0); + add_assoc_string(pval_res, "addinfo", + (char *) "PQF syntax error", 1); + RETVAL_FALSE; + } else if ((r = cql_transform_rpn2cql_stream(p->ct, wrbuf_vp_puts, + wrbuf_cql, rpn))) { + add_assoc_long(pval_res, "errorcode", r); + RETVAL_FALSE; + } else { + add_assoc_string(pval_res, "cql", + (char *) wrbuf_cstr(wrbuf_cql), 1); + RETVAL_TRUE; + } + wrbuf_destroy(wrbuf_cql); + yaz_pqf_destroy(pp); + odr_destroy(odr); + } else { + CQL_parser cp = cql_parser_create(); + int r = cql_parser_string(cp, query); + if (r) { + add_assoc_long(pval_res, "errorcode", 0); + add_assoc_string(pval_res, "addinfo", + (char *) "syntax error", 1); + RETVAL_FALSE; + } else { + WRBUF wrbuf_addinfo = wrbuf_alloc(); + WRBUF wrbuf_pqf = wrbuf_alloc(); + r = cql_transform_r(p->ct, cql_parser_result(cp), wrbuf_addinfo, + wrbuf_vp_puts, wrbuf_pqf); + if (r) { + add_assoc_long(pval_res, "errorcode", r); + if (wrbuf_len(wrbuf_addinfo)) + add_assoc_string(pval_res, "addinfo", + (char *) wrbuf_cstr(wrbuf_addinfo), 1); + RETVAL_FALSE; + } else { + wrbuf_chop_right(wrbuf_pqf); + add_assoc_string(pval_res, "rpn", + (char *) wrbuf_cstr(wrbuf_pqf), 1); + RETVAL_TRUE; + } + wrbuf_destroy(wrbuf_pqf); + wrbuf_destroy(wrbuf_addinfo); + } + cql_parser_destroy(cp); + } + } else { + RETVAL_FALSE; + } + release_assoc(p); +} +/* }}} */ + +/* {{{ proto void yaz_cql_conf(resource id, array package) + Configure CQL package */ +PHP_FUNCTION(yaz_cql_conf) +{ + zval *pval_id, *pval_package; + Yaz_Association p; + + if (ZEND_NUM_ARGS() != 2 || + zend_parse_parameters(2 TSRMLS_CC, "za", &pval_id, &pval_package) + == FAILURE) { + WRONG_PARAM_COUNT; + } + get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); + if (p) { + HashTable *ht = Z_ARRVAL_PP(&pval_package); + HashPosition pos; + zval **ent; + char *key; + + cql_transform_close(p->ct); + p->ct = cql_transform_create(); + + for (zend_hash_internal_pointer_reset_ex(ht, &pos); + zend_hash_get_current_data_ex(ht, (void**) &ent, &pos) == SUCCESS; + zend_hash_move_forward_ex(ht, &pos) + ) { + ulong idx; +#if PHP_API_VERSION > 20010101 + int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, 0, &pos); +#else + int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, &pos); +#endif + if (type != HASH_KEY_IS_STRING || Z_TYPE_PP(ent) != IS_STRING) { + continue; + } + + cql_transform_define_pattern(p->ct, key, (*ent)->value.str.val); + } + } + release_assoc(p); +} +/* }}} */ + + /* {{{ proto bool yaz_database (resource id, string databases) Specify the databases within a session */ PHP_FUNCTION(yaz_database) diff --git a/php_yaz.h b/php_yaz.h index 094dfa9..3ca0594 100644 --- a/php_yaz.h +++ b/php_yaz.h @@ -49,6 +49,8 @@ PHP_FUNCTION(yaz_es_result); PHP_FUNCTION(yaz_present); PHP_FUNCTION(yaz_ccl_conf); PHP_FUNCTION(yaz_ccl_parse); +PHP_FUNCTION(yaz_cql_parse); +PHP_FUNCTION(yaz_cql_conf); PHP_FUNCTION(yaz_database); PHP_FUNCTION(yaz_sort); PHP_FUNCTION(yaz_schema); diff --git a/tests/connect.phpt b/tests/connect.phpt new file mode 100644 index 0000000..16c0b55 --- /dev/null +++ b/tests/connect.phpt @@ -0,0 +1,20 @@ +--TEST-- +yaz_connect +--SKIPIF-- + +--FILE-- + +--FILE-- + "info:srw/cql-context-set/1/cql-v1.2", + "index.cql.serverChoice" => "1=1016", + "relation.eq" => "3=3", + "structure.*" => "4=1", + "position.any" => "6=1" + )); +if (yaz_cql_parse($z, "computer", $res, false)) { + echo $res['rpn'] . "\n"; +} else { + echo $res['errorcode'] . "\n"; +} +if (yaz_cql_parse($z, "computer and", $res, true)) { + echo $res['cql'] . "\n"; +} else { + echo $res['errorcode'] . "\n"; +} +if (yaz_cql_parse($z, "computer", $res, true)) { + echo $res['cql'] . "\n"; +} else { + echo $res['errorcode'] . "\n"; +} +if (yaz_cql_parse($z, "@and a @attr 1=1016 b", $res, true)) { + echo $res['cql'] . "\n"; +} else { + echo $res['errorcode'] . "\n"; +} +if (yaz_cql_parse($z, "@and a", $res, true)) { + echo $res['cql'] . "\n"; +} else { + echo $res['errorcode'] . "\n"; +} +--EXPECT-- +15 +@attr 3=3 @attr 4=1 @attr 6=1 @attr 1=1016 "computer" +0 +computer +a and b +0 diff --git a/tests/database.phpt b/tests/database.phpt new file mode 100644 index 0000000..2f7229d --- /dev/null +++ b/tests/database.phpt @@ -0,0 +1,21 @@ +--TEST-- +yaz_database +--SKIPIF-- + +--FILE-- + +--FILE-- + + 00366nam a22001698a 4504 + 11224466 + DLC + 00000000000000.0 + 910710c19910701nju 00010 eng + + 11224466 + + + DLC + DLC + + + 123-xyz + + + Jack Collins + + + How to program a computer + + + Penguin + + + 8710 + + + p. cm. + + -- 1.7.10.4