Hello Mark,

The attached patch should work for all recent builds of both Virtuoso
Open Source and commercial versions. It should be applied to libsrc/Wi
subdirectory of the tree of sources. The only affected target file is
virtuoso executable, other files will remain unchanged.

Best Regards,

Ivan Mikhailov
OpenLink Software
http://virtuoso.openlinksw.com

On Thu, 2010-11-25 at 11:13 +1100, Mark James wrote:
> Hi,
> I'm trying to aggregate up some particular values within the quad
> store and insert these totals as triples.
> 
> 
> Using the following statement I get the error - Message: SQ074: Line
> 18: SP030: SPARQL compiler, line 4: syntax error at 'sum' before '('
> 
> 
> SPARQL
> PREFIX INT: <http://localhost:8890/schemas/OE/>
> INSERT IN GRAPH <http://demo.clearbluewater.com.au/wsf/datasets/9/>
> {   ?order_id INT:order_cost ?order_cost .
>     ?order_id INT:order_list_price ?order_list_price .
>     ?order_id INT:order_price ?order_price .
> }
> where {{
> SELECT ?order_id, sum(?quantity*?cost_price) as ?order_cost,
> sum(?quantity*?list_price) as ?order_list_price,
> sum(?quantity*?unit_price) as ?order_price
> FROM <http://demo.clearbluewater.com.au/wsf/datasets/9/> 
> WHERE 
> { ?order_uri a INT:ORDERS . 
> ?order_uri INT:order_id ?order_id . 
> ?order_uri INT:order_of_order_items ?order_items_uri . 
> ?order_items_uri INT:quantity ?quantity . 
> ?order_items_uri INT:unit_price ?unit_price . 
> ?order_items_uri
> INT:order_items_has_product_information ?product_uri . 
> ?product_uri INT:cost_price ?cost_price .
> ?product_uri INT:list_price ?list_price .
> }
> group by ?order_id
> }};
> 
> 
> The statement works when replacing the INSERT statement with another
> select. Which seems to indicate the nested select statement syntax is
> correct. Any suggestions?
> 
> 
> Cheers
> Mark
> ------------------------------------------------------------------------------
> Increase Visibility of Your 3D Game App & Earn a Chance To Win $500!
> Tap into the largest installed PC base & get more eyes on your game by
> optimizing for Intel(R) Graphics Technology. Get started today with the
> Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
> http://p.sf.net/sfu/intelisp-dev2dev
> _______________________________________________ Virtuoso-users mailing list 
> [email protected] 
> https://lists.sourceforge.net/lists/listinfo/virtuoso-users

Index: sparql_core.c
===================================================================
RCS file: /home/staff/us-cvs/virtuoso/libsrc/Wi/sparql_core.c,v
retrieving revision 1.36.2.65
diff -u -U 10 -r1.36.2.65 sparql_core.c
--- sparql_core.c	23 Nov 2010 15:23:33 -0000	1.36.2.65
+++ sparql_core.c	26 Nov 2010 17:18:48 -0000
@@ -3104,21 +3104,21 @@
     goto aggr_checked; /* see below */
   proc_full_name = t_box_sprintf (MAX_NAME_LEN + 10, "DB.DBA.%s", sql_colon+4);
   if (CM_UPPER == case_mode)
     sqlp_upcase (proc_full_name);
   proc = sch_proc_def (isp_schema (sparp->sparp_sparqre->sparqre_qi->qi_space), proc_full_name);
   if ((NULL == proc) || (NULL == proc->qr_aggregate))
     goto aggr_checked; /* see below */
   aggregate_mode = 1;
   if (sparp->sparp_in_precode_expn)
     spar_error (sparp, "Aggregate function %.100s() is not allowed in 'precode' expressions that should be calculated before the result-set of the query", funname);
-  if (!sparp->sparp_allow_aggregates_in_expn)
+  if (!(sparp->sparp_allow_aggregates_in_expn & 1))
     spar_error (sparp, "Aggregate function %.100s() is not allowed outside result-set expressions", funname);
 aggr_checked:
   if (aggregate_mode)
     sparp->sparp_query_uses_aggregates++;
   return spartlist (sparp, 4, SPAR_FUNCALL, t_box_dv_short_string (funname), args, (ptrlong)aggregate_mode);
 }
 
 SPART *
 spar_make_sparul_mdw (sparp_t *sparp, ptrlong subtype, const char *opname, SPART *graph_precode, SPART *aux_op)
 {
Index: sparql.h
===================================================================
RCS file: /home/staff/us-cvs/virtuoso/libsrc/Wi/sparql.h,v
retrieving revision 1.24.2.40
diff -u -U 10 -r1.24.2.40 sparql.h
--- sparql.h	18 Oct 2010 15:55:26 -0000	1.24.2.40
+++ sparql.h	26 Nov 2010 16:26:11 -0000
@@ -283,21 +283,21 @@
   caddr_t sparp_text;
   int sparp_permitted_syntax;		/*!< Bitmask of permitted syntax extensions, 0 for default */
   int sparp_unictr;			/*!< Unique counter for objects */
 /* Environment of yacc */
   sparp_env_t * sparp_env;
   int sparp_lexem_buf_len;
   int sparp_total_lexems_parsed;
   spar_lexem_t *sparp_curr_lexem;
   spar_lexbmk_t sparp_curr_lexem_bmk;
   int sparp_in_precode_expn;		/*!< If nonzero (usually 1) then the parser reads precode-safe expression so it can not contain non-global variables, if bit 2 is set then even global variables are prohibited (like it is in INSERT DATA statement) */
-  int sparp_allow_aggregates_in_expn;	/*!< The parser reads result-set expressions or HAVING but not HAVING SELECT ... */
+  int sparp_allow_aggregates_in_expn;	/*!< The parser reads result-set expressions, GROUP BY, ORDER BY, or HAVING. Each bit is responsible for one level of nesting. */
   int sparp_query_uses_aggregates;	/*!< Nonzero if there is at least one aggregate in the whole source query, (not in the current SELECT!). This is solely for bypassing expanding top retvals for "plain SPARQL" queries, not for other logic of the compiler */
   int sparp_query_uses_sinvs;		/*!< Nonzero if there is at least one SERVICE invocation in the whole source query, (not in the current SELECT!). This forces (re) composing of \c sinv.param_varnames and \c sinv.retval_varnames lists */
   dk_set_t sparp_created_jsos;		/*!< Get-keyword style list of created JS objects. Object IRIs are keys, types (as free-text const char *) are values. This is solely for early (and incomplete) detection of probable errors. */
 /* Environment of lex */
   size_t sparp_text_ofs;
   size_t sparp_text_len;
   int sparp_lexlineno;			/*!< Source line number, starting from 1 */
   int sparp_lexdepth;			/*!< Lexical depth, it's equal to the current position in \c sparp_lexpars and \c sparp_lexstates */
   int sparp_rset_lexdepth_plus_1;	/*!< Lexical depth of current result set, increased by 1 (so when it's zero it means not in rset) */
   int sparp_lexpars[SPARP_MAX_LEXDEPTH+2];	/*!< Stack of not-yet-closed parenthesis */
Index: sparql_p.y
===================================================================
RCS file: /home/staff/us-cvs/virtuoso/libsrc/Wi/sparql_p.y,v
retrieving revision 1.33.2.43
diff -u -U 10 -r1.33.2.43 sparql_p.y
--- sparql_p.y	27 Oct 2010 11:43:49 -0000	1.33.2.43
+++ sparql_p.y	26 Nov 2010 17:31:03 -0000
@@ -594,21 +594,21 @@
 		t_set_push (&(sparp_env()->spare_namespace_prefixes), t_box_dv_short_nchars ($2, box_length ($2)-2)); }
 	| PREFIX_L QNAME_NS { sparyyerror ("Missing <namespace-iri-string> in PREFIX declaration"); }
 	| PREFIX_L error { sparyyerror ("Missing namespace prefix after PREFIX keyword"); }
 	;
 
 spar_select_query	/* [5]*	SelectQuery	 ::=  'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Retcol ( ','? Retcol )* ) | '*' )	*/
 			/*... DatasetClause* WhereClause SolutionModifier	*/
 	: spar_select_query_mode {
 		sparp_arg->sparp_env->spare_top_retval_selid = spar_selid_push (sparp_arg);
 		t_set_push (&(sparp_arg->sparp_env->spare_propvar_sets), NULL);
-		sparp_arg->sparp_allow_aggregates_in_expn++; }
+		sparp_arg->sparp_allow_aggregates_in_expn |= 1; }
 	    spar_select_rset spar_dataset_clauses_opt
 	    spar_where_clause spar_solution_modifier {
 		SPART *where_gp = spar_gp_finalize (sparp_arg, NULL);
 		SPART *wm = $6;
 		caddr_t retselid = spar_selid_pop (sparp_arg);
 		wm->_.wm.where_gp = where_gp;
 		$$ = spar_make_top_or_special_case_from_wm (sparp_arg, $1, $3, retselid, wm );
 		if (SPAR_REQ_TOP == $$->type)
 		  sparp_expand_top_retvals (sparp_arg, $$, 0 /* never cloned, hence 0 == safely_copy_all_vars */); }
 	;
@@ -726,32 +726,32 @@
 	;
 
 spar_precode_expn	/* [Virt]	PrecodeExpn	 ::=  Expn	(* Only global variables can occur in Expn, local can not *)	*/
 	: { sparp_arg->sparp_in_precode_expn = 1; }
 	  spar_expn
 	  { sparp_arg->sparp_in_precode_expn = 0; $$ = $2; }
 	;
 
 spar_wherebindings_clause_opt	/* ::=  (WhereClause BindingsClause?)?	*/
 	: /* nothing */ {
-		sparp_arg->sparp_allow_aggregates_in_expn--;
+		sparp_arg->sparp_allow_aggregates_in_expn &= ~1;
 		spar_gp_init (sparp_arg, WHERE_L); }
 	| spar_wherebindings_clause {;}
 	;
 
 spar_where_clause	/* [13*]	WhereClause	 ::=  'WHERE'? GroupGraphPattern	*/
 	: WHERE_L _LBRA	{
-		sparp_arg->sparp_allow_aggregates_in_expn--;
+		sparp_arg->sparp_allow_aggregates_in_expn &= ~1;
 		spar_gp_init (sparp_arg, WHERE_L); }
 	    spar_gp _RBRA spar_bindings_clause_opt {;}
 	| _LBRA {
-		sparp_arg->sparp_allow_aggregates_in_expn--;
+		sparp_arg->sparp_allow_aggregates_in_expn &= ~1;
 		spar_gp_init (sparp_arg, WHERE_L); }
 	    spar_gp _RBRA {;}
 	;
 
 spar_wherebindings_clause	/* [13*]	WhereBindingsClause	 ::=  'WHERE'? GroupGraphPattern BindingsClause?	*/
 	: spar_where_clause spar_bindings_clause_opt {;}
 	;
 
 spar_bindings_clause_opt
 	: /* nothing */		{ $$ = NULL; }
@@ -820,58 +820,58 @@
 			/*... ((LimitClause OffsetClause?) | (OffsetClause LimitClause?))?	*/
 	: spar_group_clause_opt spar_having_clause_opt spar_order_clause_opt						{ $$ = spar_make_wm (sparp_arg, NULL, (SPART **)t_revlist_to_array ($1), $2, (SPART **)t_revlist_to_array ($3), (SPART *)t_box_num (SPARP_MAXLIMIT), (SPART *)t_box_num (0)); }
 	| spar_group_clause_opt spar_having_clause_opt spar_order_clause_opt spar_limit_clause spar_offset_clause_opt	{ $$ = spar_make_wm (sparp_arg, NULL, (SPART **)t_revlist_to_array ($1), $2, (SPART **)t_revlist_to_array ($3), $4, $5); }
 	| spar_group_clause_opt spar_having_clause_opt spar_order_clause_opt spar_offset_clause spar_limit_clause_opt	{ $$ = spar_make_wm (sparp_arg, NULL, (SPART **)t_revlist_to_array ($1), $2, (SPART **)t_revlist_to_array ($3), $5, $4); }
 	;
 
 spar_group_clause_opt	/* [Virt]	GroupClause	 ::=  'GROUP' 'BY' GroupExpn+	*/
 	: /* empty */				{ $$ = NULL; }
 	| GROUP_L BY_L {
 		spar_selid_push_reused (sparp_arg, sparp_arg->sparp_env->spare_top_retval_selid);
-		sparp_arg->sparp_allow_aggregates_in_expn++; }
+		sparp_arg->sparp_allow_aggregates_in_expn |= 1; }
 	    spar_group_expns	{
 		spar_selid_pop (sparp_arg); $$ = $4;
-		sparp_arg->sparp_allow_aggregates_in_expn--; }
+		sparp_arg->sparp_allow_aggregates_in_expn &= ~1; }
 	;
 
 spar_group_expns	/* ::=  GroupExpn+	*/
 	: spar_group_expn			{ $$ = NULL; t_set_push (&($$), $1); }
 	| spar_group_expns spar_group_expn	{ $$ = $1; t_set_push (&($$), $2); }
 	;
 
 spar_group_expn		/* [Virt]	GroupExpn	 ::=  */
 			/*... ( FunctionCall | Var | ( '(' Expn ')' ) | ( '[' Expn ']' ) )	*/
 	: _LPAR spar_expn _RPAR		{ $$ = $2; }
 	| _LSQBRA spar_expn _RSQBRA	{ $$ = $2; }
 	| spar_built_in_call
 	| spar_function_call
 	| spar_var
 	;
 
 spar_having_clause_opt	/* [Virt]	HavingClause	 ::= 'HAVING' Expn */
 	: /* empty */	{ $$ = NULL; }
 	| HAVING_L {
 		spar_selid_push_reused (sparp_arg, sparp_arg->sparp_env->spare_top_retval_selid);
-		sparp_arg->sparp_allow_aggregates_in_expn++; }
+		sparp_arg->sparp_allow_aggregates_in_expn |= 1; }
 	    spar_expn {
 		spar_selid_pop (sparp_arg); $$ = $3;
-		sparp_arg->sparp_allow_aggregates_in_expn--; }
+		sparp_arg->sparp_allow_aggregates_in_expn &= ~1; }
 	;
 
 spar_order_clause_opt	/* [15]	OrderClause	 ::=  'ORDER' 'BY' OrderCondition+	*/
 	: /* empty */				{ $$ = NULL; }
 	| ORDER_L BY_L {
 		spar_selid_push_reused (sparp_arg, sparp_arg->sparp_env->spare_top_retval_selid);
-		sparp_arg->sparp_allow_aggregates_in_expn++; }
+		sparp_arg->sparp_allow_aggregates_in_expn |= 1; }
 	    spar_order_conditions	{
 		spar_selid_pop (sparp_arg); $$ = $4;
-		sparp_arg->sparp_allow_aggregates_in_expn--; }
+		sparp_arg->sparp_allow_aggregates_in_expn &= ~1; }
 	;
 
 spar_order_conditions	/* ::=  OrderCondition+	*/
 	: spar_order_condition				{ $$ = NULL; t_set_push (&($$), $1); }
 	| spar_order_conditions spar_order_condition	{ $$ = $1; t_set_push (&($$), $2); }
 	;
 
 spar_order_condition	/* [16]*	OrderCondition	 ::=  ( 'ASC' | 'DESC' )? */
 			/*... ( FunctionCall | Var | ( '(' Expn ')' ) | ( '[' Expn ']' ) )	*/
 	: spar_asc_or_desc_opt _LPAR spar_expn _RPAR		{ $$ = spartlist (sparp_arg, 3, ORDER_L, (ptrlong)$1, $3); }
@@ -909,37 +909,39 @@
 spar_group_gp		/* [19]*	GroupGraphPattern	 ::=  '{' ( GraphPattern | SelectQuery | ServiceReq ) '}'	*/
 	: spar_gp _RBRA spar_triple_optionlist_opt {
 		$$ = spar_gp_finalize (sparp_arg, $3);
 		sparp_validate_options_of_tree (sparp_arg, $$, $$->_.gp.options); }
 	| spar_select_query_mode {
 		if (NULL == sparp_env()->spare_context_sinvs) { /* There's an exception related to codegen-time optimization SERVICE { SELECT {x}} like it is SERVICE {x}, so no error right here. */
 		    SPAR_ERROR_IF_UNSUPPORTED_SYNTAX (SSG_SD_BI, "subquery"); }
 		spar_env_push (sparp_arg);
 		spar_selid_push (sparp_arg);
 		t_set_push (&(sparp_arg->sparp_env->spare_propvar_sets), NULL);
-		sparp_arg->sparp_allow_aggregates_in_expn++; }
+		sparp_arg->sparp_allow_aggregates_in_expn <<= 1;
+		sparp_arg->sparp_allow_aggregates_in_expn |= 1; }
 	    spar_select_rset spar_dataset_clauses_opt
 	    spar_where_clause spar_solution_modifier
 	    _RBRA spar_triple_optionlist_opt {
 		SPART *subselect_top;
 		SPART *where_gp;
 		caddr_t retselid;
 		SPART *wm = $6;
 		where_gp = spar_gp_finalize (sparp_arg, NULL);
 		retselid = spar_selid_pop (sparp_arg);
 		wm->_.wm.where_gp = where_gp;
 		subselect_top = spar_make_top_or_special_case_from_wm (sparp_arg,
 		  $1, $3, retselid, wm );
 		if (SPAR_REQ_TOP == subselect_top->type)
 		  sparp_expand_top_retvals (sparp_arg, subselect_top, 1 /* safely_copy_all_vars */);
 		spar_env_pop (sparp_arg);
-		$$ = spar_gp_finalize_with_subquery (sparp_arg, $8, subselect_top); }
+		$$ = spar_gp_finalize_with_subquery (sparp_arg, $8, subselect_top);
+		sparp_arg->sparp_allow_aggregates_in_expn >>= 1; }
 	;
 
 spar_gp			/* [20]	GraphPattern	 ::=  Triples? ( GraphPatternNotTriples '.'? GraphPattern )?	*/
 	: spar_triples_opt { }
 	| spar_triples_opt spar_gp_not_triples spar_gp { }
 	| spar_triples_opt spar_gp_not_triples _DOT spar_gp { }
 	;
 
 spar_gp_not_triples	/* [21]*	GraphPatternNotTriples	 ::=  */
 	: spar_quad_map_gp { spar_gp_add_member (sparp_arg, $1); }	/*... QuadMapGraphPattern	*/
@@ -1413,59 +1415,63 @@
 		else
 		  $$ = $2; }
 	| _LPAR spar_expn _RPAR	{ $$ = $2; }	/* [58]	PrimaryExpn	 ::=  */
 			/*... BracketedExpn | BuiltInCall | IRIrefOrFunction	*/
 			/*... | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | Var	*/
 	| _LPAR ASK_L {
 		SPAR_ERROR_IF_UNSUPPORTED_SYNTAX (SSG_SD_BI, "scalar ASK subquery");
 		spar_gp_init (sparp_arg, SELECT_L);
 		spar_env_push (sparp_arg);
 		spar_selid_push (sparp_arg);
-		t_set_push (&(sparp_arg->sparp_env->spare_propvar_sets), NULL); }
+		t_set_push (&(sparp_arg->sparp_env->spare_propvar_sets), NULL);
+		sparp_arg->sparp_allow_aggregates_in_expn <<= 1; }
 	    spar_dataset_clauses_opt
 	    spar_wherebindings_clause
 	    _RPAR spar_triple_optionlist_opt {
 		SPART *subselect_top;
 		SPART *where_gp;
 		where_gp = spar_gp_finalize (sparp_arg, NULL);
 		subselect_top = spar_make_top (sparp_arg, ASK_L, (SPART **)t_list(0), spar_selid_pop (sparp_arg),
 		  where_gp, NULL, NULL, NULL, (SPART *)t_box_num(1), (SPART *)t_box_num(0) );
 		spar_env_pop (sparp_arg);
-		$$ = spar_gp_finalize_with_subquery (sparp_arg, $7, subselect_top); }
+		$$ = spar_gp_finalize_with_subquery (sparp_arg, $7, subselect_top);
+		sparp_arg->sparp_allow_aggregates_in_expn >>= 1; }
 	| _LPAR spar_select_query_mode {
 		SPAR_ERROR_IF_UNSUPPORTED_SYNTAX (SSG_SD_BI, "scalar subquery");
 		spar_gp_init (sparp_arg, SELECT_L);
 		spar_env_push (sparp_arg);
 		spar_selid_push (sparp_arg);
 		t_set_push (&(sparp_arg->sparp_env->spare_propvar_sets), NULL);
-		sparp_arg->sparp_allow_aggregates_in_expn++; }
+		sparp_arg->sparp_allow_aggregates_in_expn <<= 1;
+		sparp_arg->sparp_allow_aggregates_in_expn |= 1; }
 	    spar_select_rset spar_dataset_clauses_opt
 	    spar_where_clause spar_solution_modifier
 	    _RPAR spar_triple_optionlist_opt {
 		SPART *subselect_top;
 		SPART *where_gp;
 		SPART *wm = $7;
 		caddr_t retselid;
 		where_gp = spar_gp_finalize (sparp_arg, NULL);
 		retselid = spar_selid_pop (sparp_arg);
 		wm->_.wm.where_gp = where_gp;
 		subselect_top = spar_make_top_or_special_case_from_wm (sparp_arg,
 		  $2, $4, retselid, wm );
 		if (SPAR_REQ_TOP == subselect_top->type)
 		  sparp_expand_top_retvals (sparp_arg, subselect_top, 1 /* safely_copy_all_vars */);
 		spar_env_pop (sparp_arg);
-		$$ = spar_gp_finalize_with_subquery (sparp_arg, $9, subselect_top); }
+		$$ = spar_gp_finalize_with_subquery (sparp_arg, $9, subselect_top);
+		sparp_arg->sparp_allow_aggregates_in_expn >>= 1; }
 	| spar_ret_agg_call {
 		$$ = $1;
 		if (sparp_arg->sparp_in_precode_expn)
 		  sparyyerror ("Aggregates are not allowed in 'precode' expressions that should be calculated before the result-set of the query");
-		if (!sparp_arg->sparp_allow_aggregates_in_expn)
+		if (!(sparp_arg->sparp_allow_aggregates_in_expn & 1))
 		  sparyyerror ("Aggregates are allowed only in result sets"); }
 	| spar_built_in_call
 	| spar_iriref spar_arg_list_opt {	/* [55]	IRIrefOrFunction	 ::=  IRIref ArgList? */
 		  if (NULL == $2)
 		    $$ = $1;
 		  else
 		    {
 		      SPART **args = (SPART **)(((dk_set_t)NIL_L == $2) ? NULL : t_revlist_to_array ($2));
 		      caddr_t fname = $1->_.lit.val;
 		      spar_verify_funcall_security (sparp_arg, fname, args);

Reply via email to