[tracker] rasqal: Add SUM, AVG, MIN, and MAX aggregate function support



commit 3ef25197a2a77e01bac8a3f96e59807aea1ebb9d
Author: Jürg Billeter <j bitron ch>
Date:   Wed Dec 10 17:15:14 2008 +0100

    rasqal: Add SUM, AVG, MIN, and MAX aggregate function support
---
 src/rasqal/rasqal.h        |    8 ++++
 src/rasqal/rasqal_expr.c   |   27 +++++++++++++-
 src/rasqal/sparql_lexer.l  |    4 ++
 src/rasqal/sparql_parser.y |   88 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 123 insertions(+), 4 deletions(-)

diff --git a/src/rasqal/rasqal.h b/src/rasqal/rasqal.h
index 225e34e..5dfbae3 100644
--- a/src/rasqal/rasqal.h
+++ b/src/rasqal/rasqal.h
@@ -441,6 +441,10 @@ struct rasqal_literal_s {
  * @RASQAL_EXPR_COUNT: Expression for LAQRS select COUNT()
  * @RASQAL_EXPR_VARSTAR: Expression for LAQRS select Variable *
  * @RASQAL_EXPR_SAMETERM: Expression for SPARQL sameTerm
+ * @RASQAL_EXPR_SUM: Expression for LAQRS select SUM()
+ * @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_UNKNOWN: Internal
  * @RASQAL_EXPR_LAST: Internal
  *
@@ -490,6 +494,10 @@ typedef enum {
   RASQAL_EXPR_COUNT,
   RASQAL_EXPR_VARSTAR,
   RASQAL_EXPR_SAMETERM,
+  RASQAL_EXPR_SUM,
+  RASQAL_EXPR_AVG,
+  RASQAL_EXPR_MIN,
+  RASQAL_EXPR_MAX,
   /* internal */
   RASQAL_EXPR_LAST= RASQAL_EXPR_SAMETERM
 } rasqal_op;
diff --git a/src/rasqal/rasqal_expr.c b/src/rasqal/rasqal_expr.c
index 07d99fd..1e3b76f 100644
--- a/src/rasqal/rasqal_expr.c
+++ b/src/rasqal/rasqal_expr.c
@@ -438,7 +438,8 @@ rasqal_new_0op_expression(rasqal_world* world, rasqal_op op)
  * @RASQAL_EXPR_DATATYPE @RASQAL_EXPR_ISURI @RASQAL_EXPR_ISBLANK
  * @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_GROUP_COND_DESC @RASQAL_EXPR_COUNT @RASQAL_EXPR_SUM
+ * @RASQAL_EXPR_AVG @RASQAL_EXPR_MIN @RASQAL_EXPR_MAX
  *
  * @RASQAL_EXPR_BANG and @RASQAL_EXPR_UMINUS are used by RDQL and
  * SPARQL.  @RASQAL_EXPR_TILDE by RDQL only.  The rest by SPARQL
@@ -796,6 +797,10 @@ rasqal_expression_clear(rasqal_expression* e)
     case RASQAL_EXPR_GROUP_COND_ASC:
     case RASQAL_EXPR_GROUP_COND_DESC:
     case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SUM:
+    case RASQAL_EXPR_AVG:
+    case RASQAL_EXPR_MIN:
+    case RASQAL_EXPR_MAX:
       rasqal_free_expression(e->arg1);
       break;
     case RASQAL_EXPR_STR_MATCH:
@@ -939,6 +944,10 @@ rasqal_expression_visit(rasqal_expression* e,
     case RASQAL_EXPR_GROUP_COND_ASC:
     case RASQAL_EXPR_GROUP_COND_DESC:
     case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SUM:
+    case RASQAL_EXPR_AVG:
+    case RASQAL_EXPR_MIN:
+    case RASQAL_EXPR_MAX:
       return rasqal_expression_visit(e->arg1, fn, user_data);
       break;
     case RASQAL_EXPR_STR_MATCH:
@@ -1899,6 +1908,10 @@ rasqal_expression_evaluate_v2(rasqal_world *world, raptor_locator *locator,
     case RASQAL_EXPR_GROUP_COND_ASC:
     case RASQAL_EXPR_GROUP_COND_DESC:
     case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SUM:
+    case RASQAL_EXPR_AVG:
+    case RASQAL_EXPR_MIN:
+    case RASQAL_EXPR_MAX:
       result=rasqal_expression_evaluate_v2(world, locator, e->arg1, flags);
       break;
 
@@ -2129,6 +2142,10 @@ rasqal_expression_write(rasqal_expression* e, raptor_iostream* iostr)
     case RASQAL_EXPR_GROUP_COND_ASC:
     case RASQAL_EXPR_GROUP_COND_DESC:
     case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SUM:
+    case RASQAL_EXPR_AVG:
+    case RASQAL_EXPR_MIN:
+    case RASQAL_EXPR_MAX:
       raptor_iostream_write_counted_string(iostr, "op ", 3);
       rasqal_expression_write_op(e, iostr);
       raptor_iostream_write_byte(iostr, '(');
@@ -2252,6 +2269,10 @@ rasqal_expression_print(rasqal_expression* e, FILE* fh)
     case RASQAL_EXPR_GROUP_COND_ASC:
     case RASQAL_EXPR_GROUP_COND_DESC:
     case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SUM:
+    case RASQAL_EXPR_AVG:
+    case RASQAL_EXPR_MIN:
+    case RASQAL_EXPR_MAX:
       fputs("op ", fh);
       rasqal_expression_print_op(e, fh);
       fputc('(', fh);
@@ -2373,6 +2394,10 @@ rasqal_expression_is_constant(rasqal_expression* e)
     case RASQAL_EXPR_GROUP_COND_ASC:
     case RASQAL_EXPR_GROUP_COND_DESC:
     case RASQAL_EXPR_COUNT:
+    case RASQAL_EXPR_SUM:
+    case RASQAL_EXPR_AVG:
+    case RASQAL_EXPR_MIN:
+    case RASQAL_EXPR_MAX:
       result=rasqal_expression_is_constant(e->arg1);
       break;
 
diff --git a/src/rasqal/sparql_lexer.l b/src/rasqal/sparql_lexer.l
index cf8db7b..68dee58 100644
--- a/src/rasqal/sparql_lexer.l
+++ b/src/rasqal/sparql_lexer.l
@@ -353,6 +353,10 @@ EXPONENT [eE][+-]?[0-9]+
 [Ee][Xx][Pp][Ll][Aa][Ii][Nn] { return EXPLAIN; }
 [Gg][Rr][Oo][Uu][Pp] { return GROUP; }
 [Cc][Oo][Uu][Nn][Tt] { return COUNT; }
+[Ss][Uu][Mm] { return SUM; }
+[Aa][Vv][Gg] { return AVERAGE; }
+[Mm][Ii][Nn] { return MINIMUM; }
+[Mm][Aa][Xx] { return MAXIMUM; }
 [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 7723dd0..2782cf8 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 AS
+%token EXPLAIN GROUP COUNT SUM AVERAGE MINIMUM MAXIMUM AS
 %token DELETE INSERT
 
 
@@ -218,7 +218,8 @@ static void sparql_query_error_full(rasqal_query *rq, const char *message, ...)
 %type <expr> BuiltInCall RegexExpression FunctionCall
 %type <expr> BrackettedExpression PrimaryExpression
 %type <expr> OrderCondition Filter Constraint SelectExpression
-%type <expr> AggregateExpression CountAggregateExpression
+%type <expr> AggregateExpression CountAggregateExpression SumAggregateExpression
+%type <expr> AvgAggregateExpression MinAggregateExpression MaxAggregateExpression
 
 %type <literal> GraphTerm IRIref BlankNode
 %type <literal> VarOrIRIref
@@ -296,7 +297,8 @@ MultiplicativeExpression UnaryExpression
 BuiltInCall RegexExpression FunctionCall
 BrackettedExpression PrimaryExpression
 OrderCondition Filter Constraint SelectExpression
-AggregateExpression CountAggregateExpression
+AggregateExpression CountAggregateExpression SumAggregateExpression
+AvgAggregateExpression MinAggregateExpression MaxAggregateExpression
 
 %destructor {
   if($$)
@@ -554,6 +556,22 @@ AggregateExpression: CountAggregateExpression
 {
   $$=$1;
 }
+| SumAggregateExpression
+{
+  $$=$1;
+}
+| AvgAggregateExpression
+{
+  $$=$1;
+}
+| MinAggregateExpression
+{
+  $$=$1;
+}
+| MaxAggregateExpression
+{
+  $$=$1;
+}
 ;
 
 
@@ -589,6 +607,70 @@ CountAggregateExpression: COUNT '(' Expression ')'
 ;
 
 
+SumAggregateExpression: SUM '(' Expression ')'
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended) {
+    sparql_syntax_error((rasqal_query*)rq, "SUM cannot be used with SPARQL");
+    $$=NULL;
+  } else {
+    $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_SUM, $3);
+    if(!$$)
+      YYERROR_MSG("SumAggregateExpression 1: cannot create expr");
+  }
+}
+;
+
+
+AvgAggregateExpression: AVERAGE '(' Expression ')'
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended) {
+    sparql_syntax_error((rasqal_query*)rq, "AVG cannot be used with SPARQL");
+    $$=NULL;
+  } else {
+    $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_AVG, $3);
+    if(!$$)
+      YYERROR_MSG("AvgAggregateExpression 1: cannot create expr");
+  }
+}
+;
+
+
+MinAggregateExpression: MINIMUM '(' Expression ')'
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended) {
+    sparql_syntax_error((rasqal_query*)rq, "MIN cannot be used with SPARQL");
+    $$=NULL;
+  } else {
+    $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_MIN, $3);
+    if(!$$)
+      YYERROR_MSG("MinAggregateExpression 1: cannot create expr");
+  }
+}
+;
+
+
+MaxAggregateExpression: MAXIMUM '(' Expression ')'
+{
+  rasqal_sparql_query_language* sparql=(rasqal_sparql_query_language*)(((rasqal_query*)rq)->context);
+
+  if(!sparql->extended) {
+    sparql_syntax_error((rasqal_query*)rq, "MAX cannot be used with SPARQL");
+    $$=NULL;
+  } else {
+    $$=rasqal_new_1op_expression(((rasqal_query*)rq)->world, RASQAL_EXPR_MAX, $3);
+    if(!$$)
+      YYERROR_MSG("MaxAggregateExpression 1: 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]