[tracker] SPARQL: Add support for GROUP_CONCAT
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [tracker] SPARQL: Add support for GROUP_CONCAT
- Date: Wed, 12 Aug 2009 09:08:43 +0000 (UTC)
commit 87fd1404900e9e3a2c1688cc7dce55eb05e1881f
Author: Jürg Billeter <j bitron ch>
Date: Wed Aug 12 10:55:55 2009 +0200
SPARQL: Add support for GROUP_CONCAT
src/libtracker-data/tracker-sparql-query.vala | 9 +++++++++
src/rasqal/rasqal.h | 2 ++
src/rasqal/rasqal.vapi | 3 ++-
src/rasqal/rasqal_expr.c | 7 ++++++-
src/rasqal/sparql_lexer.l | 1 +
src/rasqal/sparql_parser.y | 24 +++++++++++++++++++++++-
6 files changed, 43 insertions(+), 3 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-query.vala b/src/libtracker-data/tracker-sparql-query.vala
index 61b3c69..fac8d4f 100644
--- a/src/libtracker-data/tracker-sparql-query.vala
+++ b/src/libtracker-data/tracker-sparql-query.vala
@@ -266,6 +266,10 @@ public class Tracker.SparqlQuery : Object {
return "\"%s_u\"".printf (variable_name);
}
+ string escape_sql_string_literal (string literal) {
+ return "'%s'".printf (string.joinv ("''", literal.split ("'")));
+ }
+
string get_sql_for_expression (Rasqal.Expression expr) {
if (expr.op == Rasqal.Op.COUNT) {
return "COUNT(%s)".printf (get_sql_for_expression (expr.arg1));
@@ -277,6 +281,11 @@ public class Tracker.SparqlQuery : Object {
return "MIN(%s)".printf (get_sql_for_expression (expr.arg1));
} else if (expr.op == Rasqal.Op.MAX) {
return "MAX(%s)".printf (get_sql_for_expression (expr.arg1));
+ } else if (expr.op == Rasqal.Op.GROUP_CONCAT) {
+ var binding = new LiteralBinding ();
+ binding.literal = expr.arg2.literal.as_string ();
+ bindings.append (binding);
+ return "GROUP_CONCAT(%s,%s)".printf (get_sql_for_expression (expr.arg1), escape_sql_string_literal (expr.arg2.literal.as_string ()));
} else if (expr.op == Rasqal.Op.VARSTAR) {
return "*";
} else if (expr.op == Rasqal.Op.LITERAL) {
diff --git a/src/rasqal/rasqal.h b/src/rasqal/rasqal.h
index 5e68b13..cc54893 100644
--- a/src/rasqal/rasqal.h
+++ b/src/rasqal/rasqal.h
@@ -445,6 +445,7 @@ struct rasqal_literal_s {
* @RASQAL_EXPR_AVG: Expression for LAQRS select AVG()
* @RASQAL_EXPR_MIN: Expression for LAQRS select MIN()
* @RASQAL_EXPR_MAX: Expression for LAQRS select MAX()
+ * @RASQAL_EXPR_GROUP_CONCAT: Expression for LAQRS select GROUP_CONCAT()
* @RASQAL_EXPR_UNKNOWN: Internal
* @RASQAL_EXPR_LAST: Internal
*
@@ -498,6 +499,7 @@ typedef enum {
RASQAL_EXPR_AVG,
RASQAL_EXPR_MIN,
RASQAL_EXPR_MAX,
+ RASQAL_EXPR_GROUP_CONCAT,
/* internal */
RASQAL_EXPR_LAST= RASQAL_EXPR_SAMETERM
} rasqal_op;
diff --git a/src/rasqal/rasqal.vapi b/src/rasqal/rasqal.vapi
index 7e9e355..b5e6ea8 100644
--- a/src/rasqal/rasqal.vapi
+++ b/src/rasqal/rasqal.vapi
@@ -108,7 +108,8 @@ namespace Rasqal {
SUM,
AVG,
MIN,
- MAX
+ MAX,
+ GROUP_CONCAT
}
[Compact]
diff --git a/src/rasqal/rasqal_expr.c b/src/rasqal/rasqal_expr.c
index 1e3b76f..f7bf53d 100644
--- a/src/rasqal/rasqal_expr.c
+++ b/src/rasqal/rasqal_expr.c
@@ -439,7 +439,7 @@ rasqal_new_0op_expression(rasqal_world* world, rasqal_op op)
* @RASQAL_EXPR_ISLITERAL @RASQAL_EXPR_ORDER_COND_ASC
* @RASQAL_EXPR_ORDER_COND_DESC @RASQAL_EXPR_GROUP_COND_ASC
* @RASQAL_EXPR_GROUP_COND_DESC @RASQAL_EXPR_COUNT @RASQAL_EXPR_SUM
- * @RASQAL_EXPR_AVG @RASQAL_EXPR_MIN @RASQAL_EXPR_MAX
+ * @RASQAL_EXPR_AVG @RASQAL_EXPR_MIN @RASQAL_EXPR_MAX @RASQAL_EXPR_GROUP_CONCAT
*
* @RASQAL_EXPR_BANG and @RASQAL_EXPR_UMINUS are used by RDQL and
* SPARQL. @RASQAL_EXPR_TILDE by RDQL only. The rest by SPARQL
@@ -773,6 +773,7 @@ rasqal_expression_clear(rasqal_expression* e)
case RASQAL_EXPR_STR_NEQ:
case RASQAL_EXPR_LANGMATCHES:
case RASQAL_EXPR_SAMETERM:
+ case RASQAL_EXPR_GROUP_CONCAT:
rasqal_free_expression(e->arg1);
rasqal_free_expression(e->arg2);
break;
@@ -920,6 +921,7 @@ rasqal_expression_visit(rasqal_expression* e,
case RASQAL_EXPR_STR_NEQ:
case RASQAL_EXPR_LANGMATCHES:
case RASQAL_EXPR_SAMETERM:
+ case RASQAL_EXPR_GROUP_CONCAT:
return rasqal_expression_visit(e->arg1, fn, user_data) ||
rasqal_expression_visit(e->arg2, fn, user_data);
break;
@@ -2104,6 +2106,7 @@ rasqal_expression_write(rasqal_expression* e, raptor_iostream* iostr)
case RASQAL_EXPR_LANGMATCHES:
case RASQAL_EXPR_REGEX:
case RASQAL_EXPR_SAMETERM:
+ case RASQAL_EXPR_GROUP_CONCAT:
raptor_iostream_write_counted_string(iostr, "op ", 3);
rasqal_expression_write_op(e, iostr);
raptor_iostream_write_byte(iostr, '(');
@@ -2231,6 +2234,7 @@ rasqal_expression_print(rasqal_expression* e, FILE* fh)
case RASQAL_EXPR_LANGMATCHES:
case RASQAL_EXPR_REGEX:
case RASQAL_EXPR_SAMETERM:
+ case RASQAL_EXPR_GROUP_CONCAT:
fputs("op ", fh);
rasqal_expression_print_op(e, fh);
fputc('(', fh);
@@ -2366,6 +2370,7 @@ rasqal_expression_is_constant(rasqal_expression* e)
case RASQAL_EXPR_STR_NEQ:
case RASQAL_EXPR_LANGMATCHES:
case RASQAL_EXPR_SAMETERM:
+ case RASQAL_EXPR_GROUP_CONCAT:
result=rasqal_expression_is_constant(e->arg1) &&
rasqal_expression_is_constant(e->arg2);
break;
diff --git a/src/rasqal/sparql_lexer.l b/src/rasqal/sparql_lexer.l
index 904e2db..f8ad6cc 100644
--- a/src/rasqal/sparql_lexer.l
+++ b/src/rasqal/sparql_lexer.l
@@ -357,6 +357,7 @@ EXPONENT [eE][+-]?[0-9]+
[Aa][Vv][Gg] { return AVERAGE; }
[Mm][Ii][Nn] { return MINIMUM; }
[Mm][Aa][Xx] { return MAXIMUM; }
+[Gg][Rr][Oo][Uu][Pp]_[Cc][Oo][Nn][Cc][Aa][Tt] { return GROUP_CONCAT; }
[Aa][Ss] { BEGIN(SPID); return AS; }
[Dd][Ee][Ll][Ee][Tt][Ee] { return DELETE; }
[Ii][Nn][Ss][Ee][Rr][Tt] { return INSERT; }
diff --git a/src/rasqal/sparql_parser.y b/src/rasqal/sparql_parser.y
index 29034d1..09955cb 100644
--- a/src/rasqal/sparql_parser.y
+++ b/src/rasqal/sparql_parser.y
@@ -145,7 +145,7 @@ static void sparql_query_error_full(rasqal_query *rq, const char *message, ...)
%token ISLITERAL "isLiteral"
%token SAMETERM "sameTerm"
/* LAQRS */
-%token EXPLAIN GROUP COUNT SUM AVERAGE MINIMUM MAXIMUM AS
+%token EXPLAIN GROUP COUNT SUM AVERAGE MINIMUM MAXIMUM GROUP_CONCAT AS
%token DELETE INSERT DROP
@@ -221,6 +221,7 @@ static void sparql_query_error_full(rasqal_query *rq, const char *message, ...)
%type <expr> OrderCondition Filter Constraint SelectExpression
%type <expr> AggregateExpression CountAggregateExpression SumAggregateExpression
%type <expr> AvgAggregateExpression MinAggregateExpression MaxAggregateExpression
+%type <expr> GroupConcatAggregateExpression
%type <literal> GraphTerm IRIref BlankNode
%type <literal> VarOrIRIref
@@ -300,6 +301,7 @@ BrackettedExpression PrimaryExpression
OrderCondition Filter Constraint SelectExpression
AggregateExpression CountAggregateExpression SumAggregateExpression
AvgAggregateExpression MinAggregateExpression MaxAggregateExpression
+GroupConcatAggregateExpression
%destructor {
if($$)
@@ -608,6 +610,10 @@ AggregateExpression: CountAggregateExpression
{
$$=$1;
}
+| GroupConcatAggregateExpression
+{
+ $$=$1;
+}
;
@@ -707,6 +713,22 @@ MaxAggregateExpression: MAXIMUM '(' Expression ')'
;
+GroupConcatAggregateExpression: GROUP_CONCAT '(' Expression ',' Expression ')'
+{
+ rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+ if(!sparql->extended) {
+ sparql_syntax_error((rasqal_query*)rq, "GROUP_CONCAT cannot be used with SPARQL");
+ $$=NULL;
+ } else {
+ $$=rasqal_new_2op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_GROUP_CONCAT, $3, $5);
+ if(!$$)
+ YYERROR_MSG("GroupConcatAggregateExpression: cannot create expr");
+ }
+}
+;
+
+
/* SPARQL Grammar: [6] ConstructQuery */
ConstructQuery: CONSTRUCT ConstructTemplate
DatasetClauseListOpt WhereClauseOpt SolutionModifier
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]