CQL sortby; conversion to XML done.
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 3 May 2011 14:04:00 +0000 (16:04 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 3 May 2011 14:04:00 +0000 (16:04 +0200)
The cql_node struct has not changed size but a new type of node
CQL_NODE_SORT is new. Strictly speaking this breaks binary compatibility
so perhaps this has to be enabled "actively", by API. Bug #608.

include/yaz/cql.h
src/cql.y
src/cqlutil.c
src/xcqlutil.c

index 2c92470..c9df2ac 100644 (file)
@@ -100,6 +100,9 @@ int cql_parser_stdio(CQL_parser cp, FILE *f);
 #define CQL_NODE_ST 1
 /** \brief Node type: boolean */
 #define CQL_NODE_BOOL 2
+/** \brief Node type: sortby single spec */
+#define CQL_NODE_SORT 3
+
 /** \brief CQL parse tree (node)
  */
 struct cql_node {
@@ -134,6 +137,16 @@ struct cql_node {
             /** modifiers (NULL for no list) */
             struct cql_node *modifiers;
         } boolean;
+        /** which == CQL_NODE_SORT */
+        struct {
+            char *index;
+            /** next spec */
+            struct cql_node *next;
+            /** modifiers (NULL for no list) */
+            struct cql_node *modifiers;
+            /** search node */
+            struct cql_node *search;
+        } sort;
     } u;
 };
 
@@ -178,6 +191,11 @@ struct cql_node *cql_apply_prefix(NMEM nmem, struct cql_node *cn,
 YAZ_EXPORT
 struct cql_node *cql_node_mk_boolean(NMEM nmem, const char *op);
 
+/** \brief creates a sort single spec node. */
+YAZ_EXPORT
+struct cql_node *cql_node_mk_sort(NMEM nmem, const char *index,
+    struct cql_node *modifiers);
+
 /** \brief destroys a node and its children. */
 YAZ_EXPORT
 void cql_node_destroy(struct cql_node *cn);
@@ -193,6 +211,13 @@ struct cql_node *cql_node_dup (NMEM nmem, struct cql_node *cp);
 YAZ_EXPORT
 struct cql_node *cql_parser_result(CQL_parser cp);
 
+/** \brief returns the sortby tree of the most recently parsed CQL query.
+    \param cp CQL parser
+    \returns CQL node or NULL for failure
+*/
+YAZ_EXPORT
+struct cql_node *cql_parser_sort_result(CQL_parser cp);
+
 /** \brief converts CQL tree to XCQL and writes to user-defined stream
     \param cn CQL node (tree)
     \param pr print function
index 00d806a..4021373 100644 (file)
--- a/src/cql.y
+++ b/src/cql.y
@@ -66,17 +66,35 @@ top: {
     ((CQL_parser) parm)->top = 0;
 } cqlQuery1 sortby {
     cql_node_destroy($$.rel);
-    ((CQL_parser) parm)->top = $2.cql; 
+    if ($3.cql)
+    {
+        $3.cql->u.sort.search = $2.cql;
+        ((CQL_parser) parm)->top = $3.cql;
+    } else {
+        ((CQL_parser) parm)->top = $2.cql;
+    }
 }
 ;
 
 sortby: /* empty */
-| SORTBY sortSpec;
-
-sortSpec: sortSpec singleSpec
-| singleSpec; 
+  { $$.cql = 0; }
+| SORTBY sortSpec {
+    $$.cql = $2.cql;
+ };
+
+sortSpec: sortSpec singleSpec {
+    $$.cql = $1.cql;
+    $$.cql->u.sort.next = $2.cql;
+ }
+| singleSpec
+{
+    $$.cql = $1.cql;
+}; 
 
-singleSpec: index modifiers ;
+singleSpec: index modifiers {
+    $$.cql = cql_node_mk_sort(((CQL_parser) parm)->nmem, $1.buf, $2.cql);
+ }
+;
 
 cqlQuery1: cqlQuery
 | cqlQuery error {
@@ -395,8 +413,7 @@ int cql_parser_stream(CQL_parser cp,
     cp->getbyte = getbyte;
     cp->ungetbyte = ungetbyte;
     cp->client_data = client_data;
-    if (cp->top)
-        cql_node_destroy(cp->top);
+    cql_node_destroy(cp->top);
     cql_parse(cp);
     if (cp->top)
         return 0;
@@ -428,6 +445,7 @@ struct cql_node *cql_parser_result(CQL_parser cp)
 {
     return cp->top;
 }
+
 /*
  * Local variables:
  * c-basic-offset: 4
index 8eb25f3..7dba5a7 100644 (file)
@@ -83,6 +83,19 @@ struct cql_node *cql_node_mk_boolean(NMEM nmem, const char *op)
     return p;
 }
 
+struct cql_node *cql_node_mk_sort(NMEM nmem, const char *index,
+    struct cql_node *modifiers)
+{
+    struct cql_node *p = (struct cql_node *) nmem_malloc(nmem, sizeof(*p));
+    p->which = CQL_NODE_SORT;
+    p->u.sort.index = 0;
+    if (index)
+        p->u.sort.index = nmem_strdup(nmem, index);
+    p->u.sort.modifiers = modifiers;
+    p->u.sort.next = 0;
+    return p;
+}
+
 const char *cql_uri(void)
 {
     return "info:srw/cql-context-set/1/cql-v1.2";
@@ -144,6 +157,11 @@ void cql_node_destroy(struct cql_node *cn)
         cql_node_destroy(cn->u.boolean.left);
         cql_node_destroy(cn->u.boolean.right);
         cql_node_destroy(cn->u.boolean.modifiers);
+        break;
+    case CQL_NODE_SORT:
+        cql_node_destroy(cn->u.sort.search);
+        cql_node_destroy(cn->u.sort.next);
+        cql_node_destroy(cn->u.sort.modifiers);
     }
 }
 
index 1b15aa2..19b5036 100644 (file)
@@ -118,9 +118,36 @@ static void cql_to_xml_mod(struct cql_node *m,
     }
 }
 
+static void cql_sort_to_xml(struct cql_node *cn, 
+                         void (*pr)(const char *buf, void *client_data),
+                            void *client_data, int level)
+{
+    if (cn)
+    {
+        pr_n("<sortKeys>\n", pr, client_data, level);
+        for (; cn; cn = cn->u.sort.next)
+        {
+            pr_n("<key>\n", pr, client_data, level+2);
+            
+            if (cn->u.sort.index)
+            {
+                pr_n("<index>", pr, client_data, level+4);
+                pr_cdata(cn->u.sort.index, pr, client_data);
+                pr_n("</index>\n", pr, client_data, 0);
+
+                cql_to_xml_mod(cn->u.sort.modifiers,
+                               pr, client_data, level+6);
+            }
+            pr_n("</key>\n", pr, client_data, level+2);
+        }
+        pr_n("</sortKeys>\n", pr, client_data, level);
+    }
+}
+
 static void cql_to_xml_r(struct cql_node *cn,
                          void (*pr)(const char *buf, void *client_data),
-                         void *client_data, int level)
+                         void *client_data, int level,
+                         struct cql_node *sort_node)
 {
     if (!cn)
         return;
@@ -171,6 +198,7 @@ static void cql_to_xml_r(struct cql_node *cn,
                 pr_n("</term>\n", pr, client_data, 0);
             }
         }
+        cql_sort_to_xml(sort_node, pr, client_data, level+2);
         pr_n("</searchClause>\n", pr, client_data, level);
         break;
     case CQL_NODE_BOOL:
@@ -191,16 +219,20 @@ static void cql_to_xml_r(struct cql_node *cn,
         if (cn->u.boolean.left)
         {
             printf ("%*s<leftOperand>\n", level+2, "");
-            cql_to_xml_r(cn->u.boolean.left, pr, client_data, level+4);
+            cql_to_xml_r(cn->u.boolean.left, pr, client_data, level+4, 0);
             printf ("%*s</leftOperand>\n", level+2, "");
         }
         if (cn->u.boolean.right)
         {
             printf ("%*s<rightOperand>\n", level+2, "");
-            cql_to_xml_r(cn->u.boolean.right, pr, client_data, level+4);
+            cql_to_xml_r(cn->u.boolean.right, pr, client_data, level+4, 0);
             printf ("%*s</rightOperand>\n", level+2, "");
         }
+        cql_sort_to_xml(sort_node, pr, client_data, level+2);
         pr_n("</triple>\n", pr, client_data, level);
+        break;
+    case CQL_NODE_SORT:
+        cql_to_xml_r(cn->u.sort.search, pr, client_data, level, cn);
     }
 }
 
@@ -208,7 +240,7 @@ void cql_to_xml(struct cql_node *cn,
                 void (*pr)(const char *buf, void *client_data),
                 void *client_data)
 {
-    cql_to_xml_r(cn, pr, client_data, 0);
+    cql_to_xml_r(cn, pr, client_data, 0, 0);
 }
 
 void cql_to_xml_stdio(struct cql_node *cn, FILE *f)