#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 {
/** 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;
};
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);
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
((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 {
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;
{
return cp->top;
}
+
/*
* Local variables:
* c-basic-offset: 4
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";
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);
}
}
}
}
+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;
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:
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);
}
}
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)