xquery:eval yields NullPointerException

Thursday, 14 March 2013 · 3 messages · last reply 29 Apr 2013
ML
Marco Lettere14 Mar 2013 15:35 #
Hi all, on the way to writing a small DSL I stumbled upon the following BaseX 7.6 issue. I'm not able to explain to myself why the first two expressions of the following xquery module return correctly whereas the last yields NullPointerException (as shown in the appended stacktrace). What I'm mtrying to do is to wrap up some modification code into userfriendly function calls that can be used in mini xquery scripts to formalize xml workflow. Thank you for any help, Marco.
declare variable $globals := map {
   'change' := local:change#1,
   'generate' := local:gen#0
};

declare function local:gen(){
   <b/>
};

declare function local:change($doc){
   copy $newdoc := $doc
   modify(
     insert node <a/> as last into $newdoc
   )
   return $newdoc
};

(
   xquery:eval("copy $newdoc := <b/>
                modify(
                   insert node <a/> as last into $newdoc
                )
                return $newdoc",$globals),

   xquery:eval("$generate()", $globals),
   xquery:eval("$change($doc)", map:new( ($globals, map { "doc" := <b/>})))
)
The stacktrace and query plan: Error: Improper use? Potential bug? Your feedback is welcome: Contact: basex-talk at mailman.uni-konstanz.de Version: BaseX 7.6 Java: Oracle Corporation, 1.7.0_15 OS: Linux, i386 Stack Trace:
java.lang.NullPointerException
org.basex.query.up.expr.Transform.value(Transform.java:68)
   org.basex.query.QueryContext.value(QueryContext.java:296)
   org.basex.query.func.UserFunc.value(UserFunc.java:175)
   org.basex.query.QueryContext.value(QueryContext.java:296)
org.basex.query.func.BaseFuncCall.value(BaseFuncCall.java:68)
   org.basex.query.QueryContext.value(QueryContext.java:296)
org.basex.query.value.item.FuncItem.invValue(FuncItem.java:104)
org.basex.query.func.DynamicFunc.value(DynamicFunc.java:56)
   org.basex.query.QueryContext.value(QueryContext.java:296)
   org.basex.query.QueryContext.value(QueryContext.java:254)
   org.basex.query.func.FNXQuery.eval(FNXQuery.java:95)
   org.basex.query.func.FNXQuery.eval(FNXQuery.java:71)
   org.basex.query.func.FNXQuery.iter(FNXQuery.java:37)
   org.basex.query.QueryContext.iter(QueryContext.java:285)
   org.basex.query.expr.List$1.next(List.java:100)
org.basex.query.QueryContext.execute(QueryContext.java:524)
org.basex.query.QueryProcessor.execute(QueryProcessor.java:96)
   org.basex.core.cmd.AQuery.query(AQuery.java:77)
   org.basex.core.cmd.XQuery.run(XQuery.java:22)
   org.basex.core.Command.run(Command.java:342)
   org.basex.core.Command.exec(Command.java:321)
   org.basex.core.Command.execute(Command.java:78)
   org.basex.gui.GUI.exec(GUI.java:397)
   org.basex.gui.GUI$7.run(GUI.java:349)
Compiling:
- pre-evaluating map { "change":=function($1) as item()* {
local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } }
Optimized Query:
declare function local:change($doc) { copy $newdoc as node() := $doc
modify insert node element a { () } into $newdoc return $newdoc };
declare function local:gen() { element b { () } };
(xquery:eval("copy $newdoc := $generate()
                modify(
                   insert node <a/> as last into $newdoc
                )
                return $newdoc", map{ "change":=function($1) as item()*
{ local:change(($1)) }, "generate":=function() as item()* {
local:gen(()) } }), xquery:eval("$generate()", map{
"change":=function($1) as item()* { local:change(($1)) },
"generate":=function() as item()* { local:gen(()) } }),
xquery:eval("$change($doc)", map:new((map{ "change":=function($1) as
item()* { local:change(($1)) }, "generate":=function() as item()* {
local:gen(()) } }, map { "doc":=element b { () } }))))
Query plan:
<QueryPlan>
   <UserFuncs>
     <UserFunc name="local:change" arg0="doc">
       <Transform>
         <Let var="$newdoc as node()">
           <VarRef>
             <Var name="$doc" id="2"/>
           </VarRef>
         </Let>
         <Insert>
           <VarRef>
             <Var name="$newdoc as node()" id="3"/>
           </VarRef>
           <CElem>
             <QNm value="a" type="xs:QName"/>
           </CElem>
         </Insert>
         <VarRef>
           <Var name="$newdoc as node()" id="3"/>
         </VarRef>
       </Transform>
     </UserFunc>
     <UserFunc name="local:gen">
       <CElem>
         <QNm value="b" type="xs:QName"/>
       </CElem>
     </UserFunc>
   </UserFuncs>
   <VarStack>
     <Var name="$globals" id="0"/>
   </VarStack>
   <List>
     <FNXQuery name="eval(string[,bindings])">
       <Str value="copy $newdoc := $generate()&#x0A;
modify(&#x0A;                  insert node &lt;a/&gt; as last into
$newdoc  &#x0A; )&#x0A;               return $newdoc" type="xs:string"/>
       <Map size="2">
         <Str value="change" type="xs:string"/>
         <FuncItem type="function(item()*) as item()*">
           <Var name="$1" id="1"/>
           <BaseFuncCall name="local:change(($1))">
             <VarRef>
               <Var name="$1" id="1"/>
             </VarRef>
           </BaseFuncCall>
         </FuncItem>
         <Str value="generate" type="xs:string"/>
         <FuncItem type="function() as item()*">
           <BaseFuncCall name="local:gen(())"/>
         </FuncItem>
       </Map>
     </FNXQuery>
     <FNXQuery name="eval(string[,bindings])">
       <Str value="$generate()" type="xs:string"/>
       <Map size="2">
         <Str value="change" type="xs:string"/>
         <FuncItem type="function(item()*) as item()*">
           <Var name="$1" id="1"/>
           <BaseFuncCall name="local:change(($1))">
             <VarRef>
               <Var name="$1" id="1"/>
             </VarRef>
           </BaseFuncCall>
         </FuncItem>
         <Str value="generate" type="xs:string"/>
         <FuncItem type="function() as item()*">
           <BaseFuncCall name="local:gen(())"/>
         </FuncItem>
       </Map>
     </FNXQuery>
     <FNXQuery name="eval(string[,bindings])">
       <Str value="$change($doc)" type="xs:string"/>
       <FNMap name="new([maps[,coll]])">
         <List>
           <Map size="2">
             <Str value="change" type="xs:string"/>
             <FuncItem type="function(item()*) as item()*">
               <Var name="$1" id="1"/>
               <BaseFuncCall name="local:change(($1))">
                 <VarRef>
                   <Var name="$1" id="1"/>
                 </VarRef>
               </BaseFuncCall>
             </FuncItem>
             <Str value="generate" type="xs:string"/>
             <FuncItem type="function() as item()*">
               <BaseFuncCall name="local:gen(())"/>
             </FuncItem>
           </Map>
           <LitMap>
             <Str value="doc" type="xs:string"/>
             <CElem>
               <QNm value="b" type="xs:QName"/>
             </CElem>
           </LitMap>
         </List>
       </FNMap>
     </FNXQuery>
   </List>
</QueryPlan>
CG
Christian Grün18 Mar 2013 15:59 #
Surely looks like a bug [1]. I’d be interested if you have tried to build your query without xquery:eval. It may be worth noting that all queries using eval() calls are hardly optimizable, because a dynamically built query can do lots of unexpected things (excluding, thankfully, updates). [1] https://github.com/BaseXdb/basex/issues/662
Quoted text · Marco Lettere · 199 lines
On Thu, Mar 14, 2013 at 3:35 PM, Marco Lettere <marco.lettere at dedalus.eu> wrote: > Hi all, > on the way to writing a small DSL I stumbled upon the following BaseX 7.6 > issue. > I'm not able to explain to myself why the first two expressions of the > following xquery module return correctly whereas the last yields > NullPointerException (as shown in the appended stacktrace). > What I'm mtrying to do is to wrap up some modification code into > userfriendly function calls that can be used in mini xquery scripts to > formalize xml workflow. > Thank you for any help, > Marco. > > declare variable $globals := map { > 'change' := local:change#1, > 'generate' := local:gen#0 > }; > > declare function local:gen(){ > <b/> > }; > > declare function local:change($doc){ > copy $newdoc := $doc > modify( > insert node <a/> as last into $newdoc > ) > return $newdoc > }; > > ( > xquery:eval("copy $newdoc := <b/> > modify( > insert node <a/> as last into $newdoc > ) > return $newdoc",$globals), > > xquery:eval("$generate()", $globals), > xquery:eval("$change($doc)", map:new( ($globals, map { "doc" := <b/>}))) > ) > > The stacktrace and query plan: > > Error: > Improper use? Potential bug? Your feedback is welcome: > Contact: basex-talk at mailman.uni-konstanz.de > Version: BaseX 7.6 > Java: Oracle Corporation, 1.7.0_15 > OS: Linux, i386 > Stack Trace: > java.lang.NullPointerException > org.basex.query.up.expr.Transform.value(Transform.java:68) > org.basex.query.QueryContext.value(QueryContext.java:296) > org.basex.query.func.UserFunc.value(UserFunc.java:175) > org.basex.query.QueryContext.value(QueryContext.java:296) > org.basex.query.func.BaseFuncCall.value(BaseFuncCall.java:68) > org.basex.query.QueryContext.value(QueryContext.java:296) > org.basex.query.value.item.FuncItem.invValue(FuncItem.java:104) > org.basex.query.func.DynamicFunc.value(DynamicFunc.java:56) > org.basex.query.QueryContext.value(QueryContext.java:296) > org.basex.query.QueryContext.value(QueryContext.java:254) > org.basex.query.func.FNXQuery.eval(FNXQuery.java:95) > org.basex.query.func.FNXQuery.eval(FNXQuery.java:71) > org.basex.query.func.FNXQuery.iter(FNXQuery.java:37) > org.basex.query.QueryContext.iter(QueryContext.java:285) > org.basex.query.expr.List$1.next(List.java:100) > org.basex.query.QueryContext.execute(QueryContext.java:524) > org.basex.query.QueryProcessor.execute(QueryProcessor.java:96) > org.basex.core.cmd.AQuery.query(AQuery.java:77) > org.basex.core.cmd.XQuery.run(XQuery.java:22) > org.basex.core.Command.run(Command.java:342) > org.basex.core.Command.exec(Command.java:321) > org.basex.core.Command.execute(Command.java:78) > org.basex.gui.GUI.exec(GUI.java:397) > org.basex.gui.GUI$7.run(GUI.java:349) > Compiling: > - pre-evaluating map { "change":=function($1) as item()* { > local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } } > Optimized Query: > declare function local:change($doc) { copy $newdoc as node() := $doc modify > insert node element a { () } into $newdoc return $newdoc }; > declare function local:gen() { element b { () } }; > (xquery:eval("copy $newdoc := $generate() > modify( > insert node <a/> as last into $newdoc > ) > return $newdoc", map{ "change":=function($1) as item()* { > local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } > }), xquery:eval("$generate()", map{ "change":=function($1) as item()* { > local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } > }), xquery:eval("$change($doc)", map:new((map{ "change":=function($1) as > item()* { local:change(($1)) }, "generate":=function() as item()* { > local:gen(()) } }, map { "doc":=element b { () } })))) > Query plan: > <QueryPlan> > <UserFuncs> > <UserFunc name="local:change" arg0="doc"> > <Transform> > <Let var="$newdoc as node()"> > <VarRef> > <Var name="$doc" id="2"/> > </VarRef> > </Let> > <Insert> > <VarRef> > <Var name="$newdoc as node()" id="3"/> > </VarRef> > <CElem> > <QNm value="a" type="xs:QName"/> > </CElem> > </Insert> > <VarRef> > <Var name="$newdoc as node()" id="3"/> > </VarRef> > </Transform> > </UserFunc> > <UserFunc name="local:gen"> > <CElem> > <QNm value="b" type="xs:QName"/> > </CElem> > </UserFunc> > </UserFuncs> > <VarStack> > <Var name="$globals" id="0"/> > </VarStack> > <List> > <FNXQuery name="eval(string[,bindings])"> > <Str value="copy $newdoc := $generate()&#x0A; modify(&#x0A; > insert node &lt;a/&gt; as last into $newdoc &#x0A; )&#x0A; > return $newdoc" type="xs:string"/> > <Map size="2"> > <Str value="change" type="xs:string"/> > <FuncItem type="function(item()*) as item()*"> > <Var name="$1" id="1"/> > <BaseFuncCall name="local:change(($1))"> > <VarRef> > <Var name="$1" id="1"/> > </VarRef> > </BaseFuncCall> > </FuncItem> > <Str value="generate" type="xs:string"/> > <FuncItem type="function() as item()*"> > <BaseFuncCall name="local:gen(())"/> > </FuncItem> > </Map> > </FNXQuery> > <FNXQuery name="eval(string[,bindings])"> > <Str value="$generate()" type="xs:string"/> > <Map size="2"> > <Str value="change" type="xs:string"/> > <FuncItem type="function(item()*) as item()*"> > <Var name="$1" id="1"/> > <BaseFuncCall name="local:change(($1))"> > <VarRef> > <Var name="$1" id="1"/> > </VarRef> > </BaseFuncCall> > </FuncItem> > <Str value="generate" type="xs:string"/> > <FuncItem type="function() as item()*"> > <BaseFuncCall name="local:gen(())"/> > </FuncItem> > </Map> > </FNXQuery> > <FNXQuery name="eval(string[,bindings])"> > <Str value="$change($doc)" type="xs:string"/> > <FNMap name="new([maps[,coll]])"> > <List> > <Map size="2"> > <Str value="change" type="xs:string"/> > <FuncItem type="function(item()*) as item()*"> > <Var name="$1" id="1"/> > <BaseFuncCall name="local:change(($1))"> > <VarRef> > <Var name="$1" id="1"/> > </VarRef> > </BaseFuncCall> > </FuncItem> > <Str value="generate" type="xs:string"/> > <FuncItem type="function() as item()*"> > <BaseFuncCall name="local:gen(())"/> > </FuncItem> > </Map> > <LitMap> > <Str value="doc" type="xs:string"/> > <CElem> > <QNm value="b" type="xs:QName"/> > </CElem> > </LitMap> > </List> > </FNMap> > </FNXQuery> > </List> > </QueryPlan> > > _______________________________________________ > BaseX-Talk mailing list > BaseX-Talk at mailman.uni-konstanz.de > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
CG
Christian Grün29 Apr 2013 11:58 #
Hi Marco, the discussed bug [1] has now been fixed. Sorry for the delay. Best, Christian [1] https://github.com/BaseXdb/basex/issues/662
Quoted text · Christian Grün · 210 lines
On Mon, Mar 18, 2013 at 3:59 PM, Christian Grün <christian.gruen at gmail.com> wrote: > Surely looks like a bug [1]. I’d be interested if you have tried to > build your query without xquery:eval. It may be worth noting that all > queries using eval() calls are hardly optimizable, because a > dynamically built query can do lots of unexpected things (excluding, > thankfully, updates). > > [1] https://github.com/BaseXdb/basex/issues/662 > ___________________________ > > On Thu, Mar 14, 2013 at 3:35 PM, Marco Lettere <marco.lettere at dedalus.eu> wrote: >> Hi all, >> on the way to writing a small DSL I stumbled upon the following BaseX 7.6 >> issue. >> I'm not able to explain to myself why the first two expressions of the >> following xquery module return correctly whereas the last yields >> NullPointerException (as shown in the appended stacktrace). >> What I'm mtrying to do is to wrap up some modification code into >> userfriendly function calls that can be used in mini xquery scripts to >> formalize xml workflow. >> Thank you for any help, >> Marco. >> >> declare variable $globals := map { >> 'change' := local:change#1, >> 'generate' := local:gen#0 >> }; >> >> declare function local:gen(){ >> <b/> >> }; >> >> declare function local:change($doc){ >> copy $newdoc := $doc >> modify( >> insert node <a/> as last into $newdoc >> ) >> return $newdoc >> }; >> >> ( >> xquery:eval("copy $newdoc := <b/> >> modify( >> insert node <a/> as last into $newdoc >> ) >> return $newdoc",$globals), >> >> xquery:eval("$generate()", $globals), >> xquery:eval("$change($doc)", map:new( ($globals, map { "doc" := <b/>}))) >> ) >> >> The stacktrace and query plan: >> >> Error: >> Improper use? Potential bug? Your feedback is welcome: >> Contact: basex-talk at mailman.uni-konstanz.de >> Version: BaseX 7.6 >> Java: Oracle Corporation, 1.7.0_15 >> OS: Linux, i386 >> Stack Trace: >> java.lang.NullPointerException >> org.basex.query.up.expr.Transform.value(Transform.java:68) >> org.basex.query.QueryContext.value(QueryContext.java:296) >> org.basex.query.func.UserFunc.value(UserFunc.java:175) >> org.basex.query.QueryContext.value(QueryContext.java:296) >> org.basex.query.func.BaseFuncCall.value(BaseFuncCall.java:68) >> org.basex.query.QueryContext.value(QueryContext.java:296) >> org.basex.query.value.item.FuncItem.invValue(FuncItem.java:104) >> org.basex.query.func.DynamicFunc.value(DynamicFunc.java:56) >> org.basex.query.QueryContext.value(QueryContext.java:296) >> org.basex.query.QueryContext.value(QueryContext.java:254) >> org.basex.query.func.FNXQuery.eval(FNXQuery.java:95) >> org.basex.query.func.FNXQuery.eval(FNXQuery.java:71) >> org.basex.query.func.FNXQuery.iter(FNXQuery.java:37) >> org.basex.query.QueryContext.iter(QueryContext.java:285) >> org.basex.query.expr.List$1.next(List.java:100) >> org.basex.query.QueryContext.execute(QueryContext.java:524) >> org.basex.query.QueryProcessor.execute(QueryProcessor.java:96) >> org.basex.core.cmd.AQuery.query(AQuery.java:77) >> org.basex.core.cmd.XQuery.run(XQuery.java:22) >> org.basex.core.Command.run(Command.java:342) >> org.basex.core.Command.exec(Command.java:321) >> org.basex.core.Command.execute(Command.java:78) >> org.basex.gui.GUI.exec(GUI.java:397) >> org.basex.gui.GUI$7.run(GUI.java:349) >> Compiling: >> - pre-evaluating map { "change":=function($1) as item()* { >> local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } } >> Optimized Query: >> declare function local:change($doc) { copy $newdoc as node() := $doc modify >> insert node element a { () } into $newdoc return $newdoc }; >> declare function local:gen() { element b { () } }; >> (xquery:eval("copy $newdoc := $generate() >> modify( >> insert node <a/> as last into $newdoc >> ) >> return $newdoc", map{ "change":=function($1) as item()* { >> local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } >> }), xquery:eval("$generate()", map{ "change":=function($1) as item()* { >> local:change(($1)) }, "generate":=function() as item()* { local:gen(()) } >> }), xquery:eval("$change($doc)", map:new((map{ "change":=function($1) as >> item()* { local:change(($1)) }, "generate":=function() as item()* { >> local:gen(()) } }, map { "doc":=element b { () } })))) >> Query plan: >> <QueryPlan> >> <UserFuncs> >> <UserFunc name="local:change" arg0="doc"> >> <Transform> >> <Let var="$newdoc as node()"> >> <VarRef> >> <Var name="$doc" id="2"/> >> </VarRef> >> </Let> >> <Insert> >> <VarRef> >> <Var name="$newdoc as node()" id="3"/> >> </VarRef> >> <CElem> >> <QNm value="a" type="xs:QName"/> >> </CElem> >> </Insert> >> <VarRef> >> <Var name="$newdoc as node()" id="3"/> >> </VarRef> >> </Transform> >> </UserFunc> >> <UserFunc name="local:gen"> >> <CElem> >> <QNm value="b" type="xs:QName"/> >> </CElem> >> </UserFunc> >> </UserFuncs> >> <VarStack> >> <Var name="$globals" id="0"/> >> </VarStack> >> <List> >> <FNXQuery name="eval(string[,bindings])"> >> <Str value="copy $newdoc := $generate()&#x0A; modify(&#x0A; >> insert node &lt;a/&gt; as last into $newdoc &#x0A; )&#x0A; >> return $newdoc" type="xs:string"/> >> <Map size="2"> >> <Str value="change" type="xs:string"/> >> <FuncItem type="function(item()*) as item()*"> >> <Var name="$1" id="1"/> >> <BaseFuncCall name="local:change(($1))"> >> <VarRef> >> <Var name="$1" id="1"/> >> </VarRef> >> </BaseFuncCall> >> </FuncItem> >> <Str value="generate" type="xs:string"/> >> <FuncItem type="function() as item()*"> >> <BaseFuncCall name="local:gen(())"/> >> </FuncItem> >> </Map> >> </FNXQuery> >> <FNXQuery name="eval(string[,bindings])"> >> <Str value="$generate()" type="xs:string"/> >> <Map size="2"> >> <Str value="change" type="xs:string"/> >> <FuncItem type="function(item()*) as item()*"> >> <Var name="$1" id="1"/> >> <BaseFuncCall name="local:change(($1))"> >> <VarRef> >> <Var name="$1" id="1"/> >> </VarRef> >> </BaseFuncCall> >> </FuncItem> >> <Str value="generate" type="xs:string"/> >> <FuncItem type="function() as item()*"> >> <BaseFuncCall name="local:gen(())"/> >> </FuncItem> >> </Map> >> </FNXQuery> >> <FNXQuery name="eval(string[,bindings])"> >> <Str value="$change($doc)" type="xs:string"/> >> <FNMap name="new([maps[,coll]])"> >> <List> >> <Map size="2"> >> <Str value="change" type="xs:string"/> >> <FuncItem type="function(item()*) as item()*"> >> <Var name="$1" id="1"/> >> <BaseFuncCall name="local:change(($1))"> >> <VarRef> >> <Var name="$1" id="1"/> >> </VarRef> >> </BaseFuncCall> >> </FuncItem> >> <Str value="generate" type="xs:string"/> >> <FuncItem type="function() as item()*"> >> <BaseFuncCall name="local:gen(())"/> >> </FuncItem> >> </Map> >> <LitMap> >> <Str value="doc" type="xs:string"/> >> <CElem> >> <QNm value="b" type="xs:QName"/> >> </CElem> >> </LitMap> >> </List> >> </FNMap> >> </FNXQuery> >> </List> >> </QueryPlan> >> >> _______________________________________________ >> BaseX-Talk mailing list >> BaseX-Talk at mailman.uni-konstanz.de >> https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk

⚡Generated with XQuery