Use xquery:eval in insert statement
Friday, 12 April 2013 · 3 messages · last reply 15 Apr 2013
LJ
Lauener Jonas12 Apr 2013 17:49 #
I want to use
xquery:eval in an insert statement:declare updating function local:insert($document as xs:string, $input as element()) {
insert node $input after xquery:eval(fn:concat($document, '//', node-name($input), '[last()]'))
};
let $input := <Customer CustomerID="IZZTT"><CompanyName>App</CompanyName><ContactName>Steve Jobs</ContactName><ContactTitle>CEO in Heaven</ContactTitle><Phone>(777) 7777777777</Phone><FullAddress><Address>Apple Road 3</Address><City>Cuppertino</City><Region>OR</Region><PostalCode>00000</PostalCode><Country>Heaven</Country></FullAddress></Customer>return local:insert("doc('CustomersOrders.xml')", $input)
On the BaseX GUI it works fine, but if I want to use it with the Java Client, it fails. I use this code in Java: public final class InsertExample {
/** Hidden default constructor. */
private InsertExample() {}
/** Session reference. */
static ClientSession session;
/**
* Main method.
* @param args command-line arguments
*/
public static void main(final String[] args) {
try {
// Create a client session with host name, port, user name and password session = new ClientSession("localhost", 1984, "admin", "admin");
String command = "declare updating function local:insert($document as xs:string, $input as element()) {\n insert node $input after xquery:eval(fn:concat($document, '//', node-name($input), '[last()]'))\n};\n\nlet $input := <Customer CustomerID=\"IZZTT\"><CompanyName>App</CompanyName><ContactName>Steve Jobs</ContactName><ContactTitle>CEO in Heaven</ContactTitle><Phone>(777) 7777777777</Phone><FullAddress><Address>Apple Road 3</Address><City>Cuppertino</City><Region>OR</Region><PostalCode>00000</PostalCode><Country>Heaven</Country></FullAddress></Customer>\n\nreturn local:insert(\"doc('CustomersOrders')\", $input)";
System.out.println(command);
XQuery xquery = new XQuery(command);
System.out.println(session.execute(xquery));
// close session
session.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}When I run it, I get this exception:
Version: BaseX 7.6
Java: Oracle Corporation, 1.7.0_11
OS: Windows 8, amd64
Stack Trace:
java.lang.RuntimeException: Exclusive lock could not be acquired. org.basex.util.Util.notexpected(Util.java:53)
org.basex.io.random.TableDiskAccess.lock(TableDiskAccess.java:151) org.basex.data.DiskData.startUpdate(DiskData.java:202)
org.basex.query.up.DatabaseUpdates.startUpdate(DatabaseUpdates.java:158) org.basex.query.up.ContextModifier.apply(ContextModifier.java:86) org.basex.query.up.Updates.apply(Updates.java:120)
org.basex.query.QueryContext.update(QueryContext.java:270) org.basex.query.QueryContext.value(QueryContext.java:255)
org.basex.query.QueryContext.iter(QueryContext.java:240)
org.basex.query.QueryProcessor.iter(QueryProcessor.java:76) org.basex.core.cmd.AQuery.query(AQuery.java:84)
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.server.ClientListener.run(ClientListener.java:145) at org.basex.server.ClientSession.receive(ClientSession.java:259) at org.basex.server.ClientSession.execute(ClientSession.java:162) at org.basex.server.ClientSession.execute(ClientSession.java:167) at org.basex.server.Session.execute(Session.java:37)
at org.basex.examples.api.InsertExample.main(InsertExample.java:42)
Is this a bug in BaseX? Or how can I solve this issue?
Thanks,
Jonas
CG
Christian Grün13 Apr 2013 23:15 #
Dear Jonas,
first of all, it may be advisable to avoid
xquery:eval whenever possible, as queries without dynamic query evaluations can be optimized much better. You could e.g. rewrite your function code to something like.. let $name := node-name($input)
return insert node $input after (
doc($document)//*[node-name() = $name][last()]
)..or even avoid the slow last() function call:
let $name := node-name($input)
return insert node $input into (
doc($document)/*[node-name(*) = $name]
)Next, please note that the following query..
//Customer[last()]
..is equivalent to..
//descendant-or-self::node()/child::Customer[last()]
..and you are probably looking for..
//descendant::Customer[last()]
Sorry for teaching; let‘s go back to the reason why you actually wrote this mail.. ;) I couldn’t reproduce the issue you reported. Could you please provide me with a tiny "CustomersOrders.xml" instance, or check out if the problem persists with Version 7.7 [1]?
Thanks in advance,
Christian
[1] http://files.basex.org/releases/latest/
Quoted text · Lauener Jonas · 77 lines
On Fri, Apr 12, 2013 at 5:49 PM, Lauener Jonas <jonas.lauener at fhnw.ch> wrote: > I want to use xquery:eval in an insert statement: > declare updating function local:insert($document as xs:string, $input as element()) { > insert node $input after xquery:eval(fn:concat($document, '//', node-name($input), '[last()]')) > }; > > let $input := <Customer CustomerID="IZZTT"><CompanyName>App</CompanyName><ContactName>Steve Jobs</ContactName><ContactTitle>CEO in Heaven</ContactTitle><Phone>(777) 7777777777</Phone><FullAddress><Address>Apple Road 3</Address><City>Cuppertino</City><Region>OR</Region><PostalCode>00000</PostalCode><Country>Heaven</Country></FullAddress></Customer> > > return local:insert("doc('CustomersOrders.xml')", $input) > > On the BaseX GUI it works fine, but if I want to use it with the Java Client, it fails. I use this code in Java: > public final class InsertExample { > /** Hidden default constructor. */ > private InsertExample() {} > > /** Session reference. */ > static ClientSession session; > > /** > * Main method. > * @param args command-line arguments > */ > public static void main(final String[] args) { > try { > // Create a client session with host name, port, user name and password > session = new ClientSession("localhost", 1984, "admin", "admin"); > > String command = "declare updating function local:insert($document as xs:string, $input as element()) {\n insert node $input after xquery:eval(fn:concat($document, '//', node-name($input), '[last()]'))\n};\n\nlet $input := <Customer CustomerID=\"IZZTT\"><CompanyName>App</CompanyName><ContactName>Steve Jobs</ContactName><ContactTitle>CEO in Heaven</ContactTitle><Phone>(777) 7777777777</Phone><FullAddress><Address>Apple Road 3</Address><City>Cuppertino</City><Region>OR</Region><PostalCode>00000</PostalCode><Country>Heaven</Country></FullAddress></Customer>\n\nreturn local:insert(\"doc('CustomersOrders')\", $input)"; > System.out.println(command); > > XQuery xquery = new XQuery(command); > System.out.println(session.execute(xquery)); > > // close session > session.close(); > } catch(IOException e) { > e.printStackTrace(); > } > } > } > > When I run it, I get this exception: > Version: BaseX 7.6 > Java: Oracle Corporation, 1.7.0_11 > OS: Windows 8, amd64 > Stack Trace: > java.lang.RuntimeException: Exclusive lock could not be acquired. > org.basex.util.Util.notexpected(Util.java:53) > org.basex.io.random.TableDiskAccess.lock(TableDiskAccess.java:151) > org.basex.data.DiskData.startUpdate(DiskData.java:202) > org.basex.query.up.DatabaseUpdates.startUpdate(DatabaseUpdates.java:158) > org.basex.query.up.ContextModifier.apply(ContextModifier.java:86) > org.basex.query.up.Updates.apply(Updates.java:120) > org.basex.query.QueryContext.update(QueryContext.java:270) > org.basex.query.QueryContext.value(QueryContext.java:255) > org.basex.query.QueryContext.iter(QueryContext.java:240) > org.basex.query.QueryProcessor.iter(QueryProcessor.java:76) > org.basex.core.cmd.AQuery.query(AQuery.java:84) > 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.server.ClientListener.run(ClientListener.java:145) > at org.basex.server.ClientSession.receive(ClientSession.java:259) > at org.basex.server.ClientSession.execute(ClientSession.java:162) > at org.basex.server.ClientSession.execute(ClientSession.java:167) > at org.basex.server.Session.execute(Session.java:37) > at org.basex.examples.api.InsertExample.main(InsertExample.java:42) > > Is this a bug in BaseX? Or how can I solve this issue? > > Thanks, > Jonas > _______________________________________________ > BaseX-Talk mailing list > BaseX-Talk at mailman.uni-konstanz.de > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
LJ
Lauener Jonas15 Apr 2013 15:35 #
Dear Christian,
Thanks for your advices. They are really helpful - I'm just beginner in xquery and xpath. You second insert function didn't work with my xml file - I adapted it to:
let $name := node-name($input)
return insert node $input into (
doc($document)//*[node-name() = $name]/..
)Back to the main topic - I tried my old function with basex 7.7 and now I get this error in the basex GUI and in my java app: [XUDY0029] Target has no parent node.
In the attachment is my xml schema, if you want to try - For me, the problem is solved with the adapted insert function.
Thanks a lot,
Jonas
Quoted text · Christian Grün · 112 lines
-----Ursprüngliche Nachricht----- Von: Christian Grün [mailto:christian.gruen at gmail.com] Gesendet: Samstag, 13. April 2013 23:15 An: Lauener Jonas Cc: basex-talk at mailman.uni-konstanz.de Betreff: Re: [basex-talk] Use xquery:eval in insert statement Dear Jonas, first of all, it may be advisable to avoid xquery:eval whenever possible, as queries without dynamic query evaluations can be optimized much better. You could e.g. rewrite your function code to something like.. let $name := node-name($input) return insert node $input after ( doc($document)//*[node-name() = $name][last()] ) ..or even avoid the slow last() function call: let $name := node-name($input) return insert node $input into ( doc($document)/*[node-name(*) = $name] ) Next, please note that the following query.. //Customer[last()] ..is equivalent to.. //descendant-or-self::node()/child::Customer[last()] ..and you are probably looking for.. //descendant::Customer[last()] Sorry for teaching; let's go back to the reason why you actually wrote this mail.. ;) I couldn't reproduce the issue you reported. Could you please provide me with a tiny "CustomersOrders.xml" instance, or check out if the problem persists with Version 7.7 [1]? Thanks in advance, Christian [1] http://files.basex.org/releases/latest/ On Fri, Apr 12, 2013 at 5:49 PM, Lauener Jonas <jonas.lauener at fhnw.ch> wrote: > I want to use xquery:eval in an insert statement: > declare updating function local:insert($document as xs:string, $input as element()) { > insert node $input after xquery:eval(fn:concat($document, '//', > node-name($input), '[last()]')) }; > > let $input := <Customer > CustomerID="IZZTT"><CompanyName>App</CompanyName><ContactName>Steve > Jobs</ContactName><ContactTitle>CEO in > Heaven</ContactTitle><Phone>(777) > 7777777777</Phone><FullAddress><Address>Apple Road > 3</Address><City>Cuppertino</City><Region>OR</Region><PostalCode>00000 > </PostalCode><Country>Heaven</Country></FullAddress></Customer> > > return local:insert("doc('CustomersOrders.xml')", $input) > > On the BaseX GUI it works fine, but if I want to use it with the Java Client, it fails. I use this code in Java: > public final class InsertExample { > /** Hidden default constructor. */ > private InsertExample() {} > > /** Session reference. */ > static ClientSession session; > > /** > * Main method. > * @param args command-line arguments > */ > public static void main(final String[] args) { > try { > // Create a client session with host name, port, user name and password > session = new ClientSession("localhost", 1984, "admin", > "admin"); > > String command = "declare updating function local:insert($document as xs:string, $input as element()) {\n insert node $input after xquery:eval(fn:concat($document, '//', node-name($input), '[last()]'))\n};\n\nlet $input := <Customer CustomerID=\"IZZTT\"><CompanyName>App</CompanyName><ContactName>Steve Jobs</ContactName><ContactTitle>CEO in Heaven</ContactTitle><Phone>(777) 7777777777</Phone><FullAddress><Address>Apple Road 3</Address><City>Cuppertino</City><Region>OR</Region><PostalCode>00000</PostalCode><Country>Heaven</Country></FullAddress></Customer>\n\nreturn local:insert(\"doc('CustomersOrders')\", $input)"; > System.out.println(command); > > XQuery xquery = new XQuery(command); > System.out.println(session.execute(xquery)); > > // close session > session.close(); > } catch(IOException e) { > e.printStackTrace(); > } > } > } > > When I run it, I get this exception: > Version: BaseX 7.6 > Java: Oracle Corporation, 1.7.0_11 > OS: Windows 8, amd64 > Stack Trace: > java.lang.RuntimeException: Exclusive lock could not be acquired. > org.basex.util.Util.notexpected(Util.java:53) > org.basex.io.random.TableDiskAccess.lock(TableDiskAccess.java:151) > org.basex.data.DiskData.startUpdate(DiskData.java:202) > org.basex.query.up.DatabaseUpdates.startUpdate(DatabaseUpdates.java:158) > org.basex.query.up.ContextModifier.apply(ContextModifier.java:86) > org.basex.query.up.Updates.apply(Updates.java:120) > org.basex.query.QueryContext.update(QueryContext.java:270) > org.basex.query.QueryContext.value(QueryContext.java:255) > org.basex.query.QueryContext.iter(QueryContext.java:240) > org.basex.query.QueryProcessor.iter(QueryProcessor.java:76) > org.basex.core.cmd.AQuery.query(AQuery.java:84) > 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.server.ClientListener.run(ClientListener.java:145) > at org.basex.server.ClientSession.receive(ClientSession.java:259) > at org.basex.server.ClientSession.execute(ClientSession.java:162) > at org.basex.server.ClientSession.execute(ClientSession.java:167) > at org.basex.server.Session.execute(Session.java:37) > at > org.basex.examples.api.InsertExample.main(InsertExample.java:42) > > Is this a bug in BaseX? Or how can I solve this issue? > > Thanks, > Jonas > _______________________________________________ > BaseX-Talk mailing list > BaseX-Talk at mailman.uni-konstanz.de > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk
Written for BaseX 7.6. BaseX may have changed since: please check the current documentation.
⚡Generated with XQuery