zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #10333
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
Carlos Manuel Lopez has proposed merging lp:~zorba-coders/zorba/new-groupby into lp:zorba.
Requested reviews:
Zorba Coders (zorba-coders)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/new-groupby/+merge/108231
Implements new group by syntax, as defined in the XQuery 3.0 Spec since September 2011
The group by is converted into the syntactically equivalent combination of lets and a group by as defined by the spec.
--
https://code.launchpad.net/~zorba-coders/zorba/new-groupby/+merge/108231
Your team Zorba Coders is requested to review the proposed merge of lp:~zorba-coders/zorba/new-groupby into lp:zorba.
=== 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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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());
@@ -6047,30 +6095,22 @@
return no_state;
}
-void end_visit(const VarGetsDecl& v, void* /*visit_state*/)
+void create_letVar(const QueryLoc loc, const QName *varName, expr_t domainExpr, xqtref_t type)
{
- TRACE_VISIT_OUT();
-
- xqtref_t type = (v.get_typedecl() == NULL ? NULL : pop_tstack());
-
- if (v.get_kind() == VarGetsDecl::let_var)
- {
- expr_t domainExpr = pop_nodestack();
-
- if (domainExpr->is_updating())
+ if (domainExpr->is_updating())
throw XQUERY_EXCEPTION(err::XUST0001, ERROR_LOC(loc));
// it's important to insert the debugger before the scope is pushed.
// Otherwise, the variable in question would already be in scope for
// the debugger but no value would be bound
- QueryLoc lExpandedLocation = expandQueryLoc(v.get_name()->get_location(),
+ QueryLoc lExpandedLocation = expandQueryLoc(varName->get_location(),
domainExpr->get_loc());
wrap_in_debugger_expr(domainExpr, lExpandedLocation);
push_scope();
- var_expr_t varExpr = bind_var(loc, v.get_name(), var_expr::let_var, type);
+ var_expr_t varExpr = bind_var(loc, varName, var_expr::let_var, type);
let_clause* clause = new let_clause(theRootSctx,
loc,
@@ -6078,6 +6118,19 @@
domainExpr);
theFlworClausesStack.push_back(clause);
+}
+
+void end_visit(const VarGetsDecl& v, void* /*visit_state*/)
+{
+ TRACE_VISIT_OUT();
+
+ xqtref_t type = (v.get_typedecl() == NULL ? NULL : pop_tstack());
+
+ if (v.get_kind() == VarGetsDecl::let_var)
+ {
+ expr_t domainExpr = pop_nodestack();
+
+ create_letVar(loc, v.get_name(), domainExpr, type);
}
else
{
@@ -6377,9 +6430,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 +6465,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 +6477,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 +6491,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 +6534,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 +6571,45 @@
/*******************************************************************************
- 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();
+
+ xqtref_t type = NULL;
+ if(v.get_var_expr() != NULL)
+ {
+ expr_t gvar_expr = wrap_in_atomization(pop_nodestack());
+
+ if(v.get_var_type() != NULL)
+ {
+ type = pop_tstack();
+ gvar_expr = wrap_in_type_promotion(gvar_expr, type);
+ }
+
+ create_letVar(loc, v.get_var_name(), gvar_expr, type);
+ }
+
+ //wrap data
+ expr_t e = lookup_var(v.get_var_name(), loc, err::XPST0008);
// 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_scope();
-
- push_nodestack(e);
-
- var_expr_t ve = bind_var(loc, v.get_var_name(), var_expr::groupby_var);
+
+ push_nodestack(e.getp());
+
+ var_expr_t ve =
+ create_var(loc, v.get_var_name(), var_expr::groupby_var, type);
+
push_nodestack(ve.getp());
-
- return no_state;
-}
-
-void end_visit(const GroupSpec& v, void* /*visit_state*/)
-{
- TRACE_VISIT_OUT();
}
@@ -9425,7 +9521,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 +9538,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 +11858,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 +12604,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 +12620,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 +12629,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 +12651,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 +12703,7 @@
}
-void *begin_visit (const FTContainsExpr& v)
+void *begin_visit (const FTContainsExpr& v)
{
TRACE_VISIT ();
#ifdef ZORBA_NO_FULL_TEXT
@@ -12618,7 +12714,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
=== 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-31 20:11:22 +0000
@@ -0,0 +1,1 @@
+<numbers kind="0" even="0">3 6 9</numbers><numbers kind="1" even="0">4</numbers><numbers kind="1" even="1">1 7</numbers><numbers kind="2" even="2">5</numbers><numbers kind="2" even="0">2 8</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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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-31 20:11:22 +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>
Follow ups
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: noreply, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Markos Zaharioudakis, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-14
-
Re: [Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Markos Zaharioudakis, 2012-06-14
-
Re: [Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Markos Zaharioudakis, 2012-06-14
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-08
-
Re: [Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Zorba Build Bot, 2012-06-08
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Markos Zaharioudakis, 2012-06-08
-
[Merge] lp:~zorba-coders/zorba/new-groupby into lp:zorba
From: Markos Zaharioudakis, 2012-06-08