Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/new-groupby-alt into lp:zorba.
Requested reviews: Markos Zaharioudakis (markos-za) For more details, see: https://code.launchpad.net/~zorba-coders/zorba/new-groupby-alt/+merge/107737 Implementation of the new syntax/semantics for the group-by clause. -- https://code.launchpad.net/~zorba-coders/zorba/new-groupby-alt/+merge/107737 Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/compiler/codegen/plan_visitor.cpp' --- src/compiler/codegen/plan_visitor.cpp 2012-05-03 12:31:51 +0000 +++ src/compiler/codegen/plan_visitor.cpp 2012-05-29 08:57:31 +0000 @@ -1093,17 +1093,34 @@ const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars(); const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars(); + //Since group var exprs may reference group vars declared + //before them within the same group clause. + //We need to add to the Clause stack a partial clauseVarMap that contains the + //vars defined until the moment. + FlworClauseVarMap_t clauseVarMap = new FlworClauseVarMap(c, isGeneral); + theClauseStack.push_back(clauseVarMap); + for (ulong i = 0; i < gvars.size(); ++i) { gvars[i].first->accept(*this); + + VarRebind_t varRebind = new VarRebind; + clauseVarMap->theVarExprs.push_back(gvars[i].second.getp()); + clauseVarMap->theVarRebinds.push_back(varRebind); } for (ulong i = 0; i < ngvars.size(); ++i) { ngvars[i].first->accept(*this); + + VarRebind_t varRebind = new VarRebind; + clauseVarMap->theVarExprs.push_back(ngvars[i].second.getp()); + clauseVarMap->theVarRebinds.push_back(varRebind); } - visit_flwor_clause(c, isGeneral); + //Since we already created the clauseVarMap for the group clause, + //we don't do anything when visiting. + //visit_flwor_clause(c, isGeneral); break; } @@ -1228,24 +1245,8 @@ case flwor_clause::group_clause: { - const group_clause* gbc = static_cast<const group_clause *>(c); - const group_clause::rebind_list_t& grouping_vars = gbc->get_grouping_vars(); - const group_clause::rebind_list_t& nongrouping_vars = gbc->get_nongrouping_vars(); - - for (unsigned i = 0; i < grouping_vars.size(); ++i) - { - VarRebind_t varRebind = new VarRebind; - clauseVarMap->theVarExprs.push_back(grouping_vars[i].second.getp()); - clauseVarMap->theVarRebinds.push_back(varRebind); - } - - for (unsigned i = 0; i < nongrouping_vars.size(); ++i) - { - VarRebind_t varRebind = new VarRebind; - clauseVarMap->theVarExprs.push_back(nongrouping_vars[i].second.getp()); - clauseVarMap->theVarRebinds.push_back(varRebind); - } - + //The handling of group clauses is diferent and the clauseVarMap + //is generated within the visitor, look @ plan_visitor.cpp:1096 break; } @@ -1937,15 +1938,19 @@ for (; i >= 0; --i) { - VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp(); + //The group vars need to exist in the order they are written, as + //they can reference previous group vars. + long varPos = numGroupVars - 1 - i; + + VarRebind* varRebind = clauseVarMap->theVarRebinds[varPos].getp(); const std::vector<PlanIter_t>& varRefs = varRebind->theOutputVarRefs; - bool fastComparison = nativeColumnSort(clauseVarMap->theVarExprs[i]); + bool fastComparison = nativeColumnSort(clauseVarMap->theVarExprs[varPos]); gspecs.push_back(flwor::GroupingSpec(pop_itstack(), varRefs, - collations[i], + collations[varPos], fastComparison)); } } === modified file 'src/compiler/parser/xquery_parser.y' --- src/compiler/parser/xquery_parser.y 2012-05-16 17:25:48 +0000 +++ src/compiler/parser/xquery_parser.y 2012-05-29 08:57:31 +0000 @@ -2924,12 +2924,42 @@ GroupSpec : DOLLAR QNAME { - $$ = new GroupSpec(LOC(@$), static_cast<QName*>($2), NULL); + $$ = new GroupSpec(LOC(@$), static_cast<QName*>($2), NULL, NULL, NULL); + } + | DOLLAR QNAME GETS ExprSingle + { + $$ = new GroupSpec(LOC(@$), static_cast<QName*>($2), NULL, $4, NULL); + } + | DOLLAR QNAME TypeDeclaration GETS ExprSingle + { + $$ = new GroupSpec(LOC(@$), + static_cast<QName*>($2), + dynamic_cast<SequenceType*>($3), + $5, + NULL); + } + | DOLLAR QNAME TypeDeclaration GETS ExprSingle GroupCollationSpec + { + $$ = new GroupSpec(LOC(@$), + static_cast<QName*>($2), + dynamic_cast<SequenceType*>($3), + $5, + dynamic_cast<GroupCollationSpec*>($6)); + } + | DOLLAR QNAME GETS ExprSingle GroupCollationSpec + { + $$ = new GroupSpec(LOC(@$), + static_cast<QName*>($2), + NULL, + $4, + dynamic_cast<GroupCollationSpec*>($5)); } | DOLLAR QNAME GroupCollationSpec { $$ = new GroupSpec(LOC(@$), static_cast<QName*>($2), + NULL, + NULL, dynamic_cast<GroupCollationSpec*>($3)); } ; === modified file 'src/compiler/parsetree/parsenodes.cpp' --- src/compiler/parsetree/parsenodes.cpp 2012-05-03 12:31:51 +0000 +++ src/compiler/parsetree/parsenodes.cpp 2012-05-29 08:57:31 +0000 @@ -1774,16 +1774,28 @@ vector<rchandle<GroupSpec> >::const_iterator ite = theSpecs.begin(); vector<rchandle<GroupSpec> >::const_iterator end = theSpecs.end(); - for (; ite != end; ++ite) + //If no expression is given, then it'll just be the variable. + //If this is the case, and the variable is already defined as a + //grouping variable, it makes no sense to add it, so this is a + //quick optimization. + if(spec->get_var_expr() == NULL) { - const GroupSpec* currSpec = (*ite).getp(); - - if (*currSpec->get_var_name() == *spec->get_var_name()) - break; + for (; ite != end; ++ite) + { + const GroupSpec* currSpec = (*ite).getp(); + + if (*currSpec->get_var_name() == *spec->get_var_name() && + currSpec->get_var_expr() == NULL) + break; + } + + if (ite == end) + theSpecs.push_back(spec); } - - if (ite == end) + else + { theSpecs.push_back(spec); + } } @@ -1805,10 +1817,14 @@ GroupSpec::GroupSpec( const QueryLoc& loc_, rchandle<QName> _var_name_h, + rchandle<SequenceType> _var_type_h, + rchandle<exprnode> _var_value_h, rchandle<GroupCollationSpec> _group_coll_spec_h) : parsenode(loc_), var_name_h(_var_name_h), + var_type_h(_var_type_h), + var_init_expr_h(_var_value_h), group_coll_spec_h(_group_coll_spec_h) { } @@ -1817,7 +1833,9 @@ void GroupSpec::accept(parsenode_visitor& v) const { BEGIN_VISITOR(); + ACCEPT (var_type_h); ACCEPT (group_coll_spec_h); + ACCEPT (var_init_expr_h); END_VISITOR(); } === modified file 'src/compiler/parsetree/parsenodes.h' --- src/compiler/parsetree/parsenodes.h 2012-05-16 17:16:44 +0000 +++ src/compiler/parsetree/parsenodes.h 2012-05-29 08:57:31 +0000 @@ -2207,22 +2207,30 @@ /******************************************************************************* - GroupSpec ::= "$" VarName ("collation" URILiteral)? + GroupSpec ::= "$" VarName (TypeDeclaration? ":=" ExprSingle)? ("collation" URILiteral)? ********************************************************************************/ class GroupSpec : public parsenode { protected: rchandle<QName> var_name_h; rchandle<GroupCollationSpec> group_coll_spec_h; + rchandle<exprnode> var_init_expr_h; + rchandle<SequenceType> var_type_h; public: GroupSpec( const QueryLoc&, rchandle<QName>, + rchandle<SequenceType>, + rchandle<exprnode>, rchandle<GroupCollationSpec>); const QName* get_var_name() const { return var_name_h.getp(); } + const rchandle<exprnode> get_var_expr() const {return var_init_expr_h;} + + const rchandle<SequenceType> get_var_type() const {return var_type_h;} + rchandle<GroupCollationSpec> group_coll_spec() const { return group_coll_spec_h; } void accept(parsenode_visitor&) const; @@ -3106,7 +3114,7 @@ protected: rchandle<exprnode> left; rchandle<exprnode> right; - + public: StringConcatExpr( const QueryLoc& aLoc, === modified file 'src/compiler/translator/translator.cpp' --- src/compiler/translator/translator.cpp 2012-05-09 23:06:41 +0000 +++ src/compiler/translator/translator.cpp 2012-05-29 08:57:31 +0000 @@ -717,7 +717,7 @@ } -~TranslatorImpl() +~TranslatorImpl() { #ifndef ZORBA_NO_FULL_TEXT while (!theFTNodeStack.empty()) @@ -1223,7 +1223,7 @@ method raises error. If var is not found, the method raises the given error, unless the given error - is MAX_ZORBA_ERROR_CODE, in which case it returns NULL. + is zerr::ZXQP0000_NO_ERROR, in which case it returns NULL. ********************************************************************************/ var_expr* lookup_var( const QName* qname, @@ -1780,7 +1780,7 @@ if (typeid(c) == typeid(ForClause)) { - const VarInDeclList& varDecls = + const VarInDeclList& varDecls = *(static_cast<const ForClause*>(&c)->get_vardecl_list()); for (int j = (int)varDecls.size() - 1; j >= 0; --j) @@ -1795,7 +1795,7 @@ } else if (typeid(c) == typeid(LetClause)) { - const VarGetsDeclList& lV = + const VarGetsDeclList& lV = *(static_cast<const LetClause*>(&c)->get_vardecl_list()); for (int j = (int)lV.size() - 1; j >= 0; --j) @@ -1839,6 +1839,16 @@ } else if (typeid (c) == typeid (GroupByClause)) { + const GroupByClause groupClause = *static_cast<const GroupByClause*>(&c); + + //Group-by clauses may define new variables, otherwise it shadows existing vars. + for(size_t gSpecPos = 0; gSpecPos < groupClause.get_spec_list()->size(); gSpecPos++) + { + GroupSpec *groupSpec = (*(groupClause.get_spec_list()))[gSpecPos]; + if(groupSpec->get_var_expr() != NULL) + vars.insert(lookup_var(groupSpec->get_var_name(), loc, err::XPST0008)); + } + // Group-by redefines ALL previous variables, but the GroupByClause lists // only the grouping vars. So, to find the var_exprs for the vars defined // by the GroupByClause, we exploit the fact that the redefined var_exprs @@ -2285,7 +2295,7 @@ // If an appliaction set a type for the context item via the c++ api, then // create a full declaration for it in order to enforce that type. - if (!theHaveContextItemDecl && + if (!theHaveContextItemDecl && theSctx->get_context_item_type() != theRTM.ITEM_TYPE_ONE.getp()) { var_expr* var = lookup_ctx_var(DOT_VARNAME, loc); @@ -3310,6 +3320,44 @@ qnameItem->getLocalName()))); } +<<<<<<< TREE +======= +#ifndef ZORBA_NO_FULL_TEXT + if (qnameItem->getNamespace() == static_context::ZORBA_FULL_TEXT_FN_NS && + (qnameItem->getLocalName() == "tokenizer-properties" || + qnameItem->getLocalName() == "tokenize")) + { + FunctionConsts::FunctionKind kind; + + if (qnameItem->getLocalName() == "tokenizer-properties") + { + assert(numParams <= 1); + + if (numParams == 1) + kind = FunctionConsts::FULL_TEXT_TOKENIZER_PROPERTIES_1; + else + kind = FunctionConsts::FULL_TEXT_TOKENIZER_PROPERTIES_0; + + f = new full_text_tokenizer_properties(f->getSignature(), kind); + } + else + { + assert(numParams == 1 || numParams == 2); + + if (numParams == 2) + kind = FunctionConsts::FULL_TEXT_TOKENIZE_2; + else + kind = FunctionConsts::FULL_TEXT_TOKENIZE_1; + + f = new full_text_tokenize(f->getSignature(), kind); + } + + f->setStaticContext(theRootSctx); + bind_fn(f, numParams, loc); + } +#endif /* ZORBA_NO_FULL_TEXT */ + +>>>>>>> MERGE-SOURCE f->setAnnotations(theAnnotations); theAnnotations = NULL; // important to reset @@ -3625,7 +3673,7 @@ { //lc->setLazyEval(!f->isSequential()); - const user_function* udf = + const user_function* udf = static_cast<const user_function*>(theCurrentPrologVFDecl.getFunction()); arg_var->set_param_pos(flwor->num_clauses()); @@ -3795,7 +3843,7 @@ bind_var(ve, export_sctx); #ifdef ZORBA_WITH_DEBUGGER - if (initExpr != NULL && theCCB->theDebuggerCommons != NULL) + if (initExpr != NULL && theCCB->theDebuggerCommons != NULL) { QueryLoc lExpandedLocation = expandQueryLoc(v.get_name()->get_location(), initExpr->get_loc()); @@ -6377,9 +6425,23 @@ for (int i = 0; i < (int)lList->size(); ++i) { GroupSpec* spec = (*lList)[i]; + const QName* varname = spec->get_var_name(); - const var_expr* ve = lookup_var(varname, loc, err::XPST0008); - group_vars.insert(ve); + + const var_expr* ve = NULL; + if(spec->get_var_expr() == NULL) + { + ve = lookup_var(varname, loc, err::XPST0008); + } + else + { + //variables can be explicitly shadowed, if we don't check for that + //we might have them become non-group variables incorrectly. + ve = lookup_var(varname, loc, zerr::ZXQP0000_NO_ERROR); + } + + if(ve != NULL) + group_vars.insert(ve); } // The non-grouping vars are the vars in the difference of the 2 sets above. @@ -6398,9 +6460,7 @@ { push_nodestack(const_cast<var_expr *>(*i)); - push_scope(); - - var_expr_t ve = bind_var(loc, (*i)->get_name(), var_expr::non_groupby_var); + var_expr_t ve = create_var(loc, (*i)->get_name(), var_expr::non_groupby_var); push_nodestack(ve.getp()); } @@ -6412,6 +6472,7 @@ { TRACE_VISIT_OUT(); + // NOTE: Now grouping vars have a expr for the input stream. // At this point, the nodestack contains a pair of var_exprs for each var X // defined by any clauses appearing before this GroupByClause. The first // var_expr in the pair corresponds to the input-stream var X, and the second @@ -6425,28 +6486,40 @@ std::vector<std::string> collations; group_clause::rebind_list_t grouping_rebind; group_clause::rebind_list_t nongrouping_rebind; + expr_t input_expr; var_expr_t input_var; var_expr_t output_var; + std::vector<var_expr_t> output_vars_helper; for (int i = (int)numGroupSpecs - 1; i >= 0; i--) { const GroupSpec& groupSpec = *groupSpecs[i]; output_var = pop_nodestack_var(); - input_var = pop_nodestack_var(); + input_expr = pop_nodestack(); + + output_vars_helper.push_back(output_var); if (groupSpec.group_coll_spec() != NULL) collations.push_back(groupSpec.group_coll_spec()->get_uri().str()); else collations.push_back (""); - wrapper_expr_t input_wrapper; - input_wrapper = new wrapper_expr(theRootSctx, + if(input_expr->get_expr_kind() == var_expr_kind) + input_expr = new wrapper_expr(theRootSctx, loc, - static_cast<expr*>(input_var.getp())); - - grouping_rebind.push_back(std::pair<wrapper_expr_t, var_expr_t>(input_wrapper, - output_var)); + input_expr.getp()); + + grouping_rebind.push_back(std::pair<expr_t, var_expr_t>(input_expr, + output_var)); + } + + for(std::vector<var_expr_t>::reverse_iterator iter = output_vars_helper.rbegin(); + iter != output_vars_helper.rend(); + iter++) + { + /*push_scope(); + bind_var(*iter, theSctx);*/ } reverse(collations.begin(), collations.end()); @@ -6456,6 +6529,9 @@ { input_var = pop_nodestack_var(); + push_scope(); + bind_var(output_var, theSctx); + wrapper_expr_t input_wrapper; input_wrapper = new wrapper_expr(theRootSctx, loc, @@ -6490,30 +6566,43 @@ /******************************************************************************* - GroupSpec ::= "$" VarName ("collation" URILiteral)? + GroupSpec ::= "$" VarName (TypeDeclaration? ":=" ExprSingle)? ("collation" URILiteral)? ********************************************************************************/ void* begin_visit(const GroupSpec& v) { TRACE_VISIT(); - - var_expr* e = lookup_var(v.get_var_name(), loc, err::XPST0008); + return no_state; +} + +void end_visit(const GroupSpec& v, void* /*visit_state*/) +{ + TRACE_VISIT_OUT(); + + //wrap data + expr_t e = (v.get_var_expr() != NULL) ? + wrap_in_atomization(pop_nodestack()) : lookup_var(v.get_var_name(), loc, err::XPST0008); + + //wrap type + xqtref_t type = NULL; + if(v.get_var_type() != NULL) + { + type = pop_tstack(); + e = wrap_in_type_promotion(e, type); + } // Create a new var_expr gX, corresponding to the input-stream var X that // is referenced by this group spec. gX represents X in the output stream. // Push the var_exprs for both X and gX into the nodestack. + + push_nodestack(e.getp()); + + var_expr_t ve = + create_var(loc, v.get_var_name(), var_expr::groupby_var, type); + + push_nodestack(ve.getp()); + push_scope(); - - push_nodestack(e); - - var_expr_t ve = bind_var(loc, v.get_var_name(), var_expr::groupby_var); - push_nodestack(ve.getp()); - - return no_state; -} - -void end_visit(const GroupSpec& v, void* /*visit_state*/) -{ - TRACE_VISIT_OUT(); + bind_var(ve.getp(), theSctx); } @@ -9425,7 +9514,7 @@ expr_t right = pop_nodestack(); expr_t left = pop_nodestack(); concat_args.push_back(left); - + //If the right leaf is the concat expr, //we add directly its leafs to the new concat expr. bool rightLeafIsConcatExpr = false; @@ -9442,13 +9531,13 @@ } } } - + if(!rightLeafIsConcatExpr) { concat_args.push_back(right); } - rchandle<expr> concat = new fo_expr(theRootSctx, loc, GET_BUILTIN_FUNCTION(FN_CONCAT_N), concat_args); + rchandle<expr> concat = new fo_expr(theRootSctx, loc, GET_BUILTIN_FUNCTION(FN_CONCAT_N), concat_args); push_nodestack(concat); } @@ -11762,7 +11851,7 @@ store::Item_t qnameItem; expand_elem_qname(qnameItem, qname, loc); - xqtref_t t = CTX_TM->create_named_atomic_type(qnameItem, TypeConstants::QUANT_ONE); + xqtref_t t = CTX_TM->create_named_atomic_type(qnameItem, TypeConstants::QUANT_ONE); // some types that should never be parsed, like xs:untyped, are; // we catch them with is_simple() @@ -12508,7 +12597,7 @@ #ifndef ZORBA_NO_FULL_TEXT -template<typename FTNodeType> bool flatten( ftnode *n ) +template<typename FTNodeType> bool flatten( ftnode *n ) { if ( FTNodeType *const n2 = dynamic_cast<FTNodeType*>( n ) ) { typename FTNodeType::ftnode_list_t &list = n2->get_node_list(); @@ -12524,7 +12613,7 @@ } #endif /* ZORBA_NO_FULL_TEXT */ -void *begin_visit (const FTAnd& v) +void *begin_visit (const FTAnd& v) { TRACE_VISIT (); #ifndef ZORBA_NO_FULL_TEXT @@ -12533,7 +12622,7 @@ return no_state; } -void end_visit (const FTAnd& v, void* /*visit_state*/) +void end_visit (const FTAnd& v, void* /*visit_state*/) { TRACE_VISIT_OUT (); #ifndef ZORBA_NO_FULL_TEXT @@ -12555,44 +12644,44 @@ } -void *begin_visit (const FTAnyallOption& v) -{ - TRACE_VISIT (); - // nothing to do - return no_state; -} - - -void end_visit (const FTAnyallOption& v, void* /*visit_state*/) -{ - TRACE_VISIT_OUT (); - // nothing to do -} - - -void *begin_visit (const FTBigUnit& v) -{ - TRACE_VISIT (); - // nothing to do - return no_state; -} - - -void end_visit (const FTBigUnit& v, void* /*visit_state*/) -{ - TRACE_VISIT_OUT (); - // nothing to do -} - -void *begin_visit (const FTCaseOption& v) -{ - TRACE_VISIT (); - // nothing to do - return no_state; -} - - -void end_visit (const FTCaseOption& v, void* /*visit_state*/) +void *begin_visit (const FTAnyallOption& v) +{ + TRACE_VISIT (); + // nothing to do + return no_state; +} + + +void end_visit (const FTAnyallOption& v, void* /*visit_state*/) +{ + TRACE_VISIT_OUT (); + // nothing to do +} + + +void *begin_visit (const FTBigUnit& v) +{ + TRACE_VISIT (); + // nothing to do + return no_state; +} + + +void end_visit (const FTBigUnit& v, void* /*visit_state*/) +{ + TRACE_VISIT_OUT (); + // nothing to do +} + +void *begin_visit (const FTCaseOption& v) +{ + TRACE_VISIT (); + // nothing to do + return no_state; +} + + +void end_visit (const FTCaseOption& v, void* /*visit_state*/) { TRACE_VISIT_OUT (); #ifndef ZORBA_NO_FULL_TEXT @@ -12607,7 +12696,7 @@ } -void *begin_visit (const FTContainsExpr& v) +void *begin_visit (const FTContainsExpr& v) { TRACE_VISIT (); #ifdef ZORBA_NO_FULL_TEXT @@ -12618,7 +12707,7 @@ return no_state; } -void end_visit (const FTContainsExpr& v, void* /*visit_state*/) +void end_visit (const FTContainsExpr& v, void* /*visit_state*/) { TRACE_VISIT_OUT (); #ifndef ZORBA_NO_FULL_TEXT === modified file 'src/runtime/core/flwor_iterator.h' --- src/runtime/core/flwor_iterator.h 2012-05-03 12:31:51 +0000 +++ src/runtime/core/flwor_iterator.h 2012-05-29 08:57:31 +0000 @@ -242,7 +242,7 @@ GroupingSpecList ::= GroupingSpec ("," GroupingSpec)* - GroupingSpec ::= "$" VarName ("collation" URILiteral)? + GroupingSpec ::= "$" VarName (TypeDeclaration? ":=" ExprSingle)? ("collation" URILiteral)? - Data Members: === added file 'test/rbkt/ExpQueryResults/zorba/groupby/groupby27.xml.res' --- test/rbkt/ExpQueryResults/zorba/groupby/groupby27.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/groupby/groupby27.xml.res 2012-05-29 08:57:31 +0000 @@ -0,0 +1,1 @@ +<numbers kind="0" even="0">3 6 9</numbers><numbers kind="1" even="0">2 4</numbers><numbers kind="1" even="1">7</numbers><numbers kind="2" even="0">8</numbers><numbers kind="2" even="2">5</numbers> === added file 'test/rbkt/ExpQueryResults/zorba/groupby/groupby28.xml.res' --- test/rbkt/ExpQueryResults/zorba/groupby/groupby28.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/groupby/groupby28.xml.res 2012-05-29 08:57:31 +0000 @@ -0,0 +1,1 @@ +<numbers even="true">2 4 6 8</numbers><numbers even="false">1 3 5 7</numbers> === added file 'test/rbkt/ExpQueryResults/zorba/groupby/groupby29.xml.res' --- test/rbkt/ExpQueryResults/zorba/groupby/groupby29.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/groupby/groupby29.xml.res 2012-05-29 08:57:31 +0000 @@ -0,0 +1,1 @@ +<numbers group="0">2 3 4 6 8 9</numbers><numbers group="1">1 7</numbers><numbers group="2">5</numbers> === added file 'test/rbkt/ExpQueryResults/zorba/groupby/groupby30.xml.res' --- test/rbkt/ExpQueryResults/zorba/groupby/groupby30.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/groupby/groupby30.xml.res 2012-05-29 08:57:31 +0000 @@ -0,0 +1,1 @@ +<grp y="1" even="0">2 4 6 8 10</grp><grp y="1" even="1">1 3 5 7 9</grp><grp y="2" even="1">1 3 5 7 9</grp><grp y="3" even="1">1 3 5 7 9</grp><grp y="4" even="1">1 3 5 7 9</grp><grp y="2" even="0">2 4 6 8 10</grp><grp y="3" even="0">2 4 6 8 10</grp><grp y="4" even="0">2 4 6 8 10</grp> === added file 'test/rbkt/Queries/zorba/groupby/groupby27.xq' --- test/rbkt/Queries/zorba/groupby/groupby27.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/groupby/groupby27.xq 2012-05-29 08:57:31 +0000 @@ -0,0 +1,4 @@ +for $x in (1,2,3,4,5,6,7,8,9) +let $kind := $x +group by $kind := $kind mod 3, $even := $kind * ($x mod 2) +return <numbers kind="{$kind}" even="{$even}">{$x}</numbers> === added file 'test/rbkt/Queries/zorba/groupby/groupby28.xq' --- test/rbkt/Queries/zorba/groupby/groupby28.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/groupby/groupby28.xq 2012-05-29 08:57:31 +0000 @@ -0,0 +1,3 @@ +for $x in (1,2,3,4,5,6,7,8) +group by $even as xs:integer := $x mod 2 +return <numbers even="{$even eq 0}">{$x}</numbers> === added file 'test/rbkt/Queries/zorba/groupby/groupby29.xq' --- test/rbkt/Queries/zorba/groupby/groupby29.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/groupby/groupby29.xq 2012-05-29 08:57:31 +0000 @@ -0,0 +1,5 @@ +(: Explicit shadowing should be valid :) +for $x in (1,2,3,4,5,6,7,8,9) +let $kind := $x mod 3 +group by $kind := $kind * ($x mod 2) +return <numbers group="{$kind}">{$x}</numbers> === added file 'test/rbkt/Queries/zorba/groupby/groupby30.xq' --- test/rbkt/Queries/zorba/groupby/groupby30.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/groupby/groupby30.xq 2012-05-29 08:57:31 +0000 @@ -0,0 +1,4 @@ +for $x in 1 to 10, $y in 1 to 4 +let $org_y := $y +group by $y, $y := $x mod 2 +return <grp y="{$org_y[1]}" even="{$y}">{$x}</grp>
-- Mailing list: https://launchpad.net/~zorba-coders Post to : zorba-coders@lists.launchpad.net Unsubscribe : https://launchpad.net/~zorba-coders More help : https://help.launchpad.net/ListHelp