When I try to update a node I get the error "Cannot Update constructed nodes" - xquery

When I try to update a node using the XQuery below I get the error XDMP-UPCONSTNODES: xdmp:node-replace(...) "Cannot Update constructed nodes"
let $_ := xdmp:node-replace($mydoc/docVersions, $otherVersions)

This is because the built in node-replace doesn't work on in-memory documents.
You can use the in-mem-update.xqy versions to do this.
import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';
let $_ := mem:node-replace($mydoc/docVersions, $otherVersions)

Related

bus error on usage of rusqlite with spatialite extension

I'm seeing a bus error on cargo run when attempting to load the spatialite extension with rusqlite:
Finished dev [unoptimized + debuginfo] target(s) in 1.19s
Running `target/debug/rust-spatialite-example`
[1] 33253 bus error cargo run --verbose
My suspicion is that there's a mismatch of sqlite version and spatialite and that they need to be built together rather than using the bundled feature of rusqlite, though it seems like that'd result in a different error?
Here's how things are set up:
Cargo.toml
[package]
name = "rust-spatialite-example"
version = "0.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rusqlite = { version = "0.28.0", features = ["load_extension", "bundled"] }
init.sql
CREATE TABLE place (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
SELECT AddGeometryColumn('place', 'geom', 4326, 'POINT', 'XY', 0);
SELECT CreateSpatialIndex('place', 'geom');
main.rs
use rusqlite::{Connection, Result, LoadExtensionGuard};
#[derive(Debug)]
struct Place {
id: i32,
name: String,
geom: String,
}
fn load_spatialite(conn: &Connection) -> Result<()> {
unsafe {
let _guard = LoadExtensionGuard::new(conn)?;
conn.load_extension("/opt/homebrew/Cellar/libspatialite/5.0.1_2/lib/mod_spatialite", None)
}
}
fn main() -> Result<()> {
let conn = Connection::open("./geo.db")?;
load_spatialite(&conn)?;
// ... sql statements that aren't executed
Ok(())
}
Running:
cat init.sql | spatialite geo.db
cargo run
The mod_spatialite path is correct (there's an expected SqliteFailure error when that path is wrong). I tried explicitly setting sqlite3_modspatialite_init as the entry point and the behavior stayed the same.

how to load custom dictionary in marklogic using gradle?

I have to execute following custom-dictionary.xqy file using gradle
xquery version "1.0-ml";
import module namespace cdict = "http://marklogic.com/xdmp/custom-dictionary" at "/MarkLogic/custom-dictionary.xqy";
import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';
declare default element namespace "http://marklogic.com/xdmp/custom-dictionary";
let $lang := 'en'
let $terms := <dictionary xmlns="http://marklogic.com/xdmp/custom-dictionary">
<entry>
<word>meeting</word>
<stem>meets</stem>
</entry>
</dictionary>
let $dict-exists := <a>{cdict:dictionary-read($lang)}</a>
return
(if($dict-exists/*)
then
let $new-dict := mem:node-insert-child($dict-exists//dictionary,$terms//entry)
return
cdict:dictionary-write($lang,$new-dict/dictionary)
else
cdict:dictionary-write($lang,$terms)
,"Success"
)
and I am adding a task in build.gradle file to execute the XQuery module
task addDictionary(type: com.marklogic.gradle.task.ServerEvalTask) {
client = mlAppConfig.newAppServicesDatabaseClient("databaseName")
xquery = "xdmp:invoke('path of custom-dictionary.xqy')"
}
But getting following error
Execution failed for task ':addDictionary'.
> Local message: failed to apply resource at eval: Internal Server Error. Server Message: Server (not a REST instance?) did not respond with an expected REST Error message.
I am not getting where I am doing wrong. Is there any other way to execute an XQuery using a gradle task?

Saxon xquery validation fails - help needed to understand behavior

Whilst i am using Saxon java api to execute the following xQuery, i am unable to understand why the following execution / validation fails ? (Interestingly , when i replace and clause with or in the if statement, the query validation is successful but am unable to understand this behaviour )
In oxygen xml validator, when i open the xQuery, i get NullPointerException-null exception and the validation fails.
And in java , i get the following area
java.lang.NullPointerException
at net.sf.saxon.expr.parser.LoopLifter.markDependencies(LoopLifter.java:168)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:112)
I am looking up for some experts to help me understand why the following fails.
Following is the xQuery,
declare function local:method($input as element(input)) as element(output)
{
<output>
<itemADetails>
<service>
{
for $i in 1 to count($input/*:foo)
return
for $j in 1 to count($input/*:bar)
return
if((data($input/*:foo[$i]/*:itemB[1]/*:rangeQualifier)="A") and (data($input/*:foo[$i]/*:serviceId/*:type)="B") ) then
<node></node>
else()
}
</service>
</itemADetails>
</output>
};
declare variable $input as element(input) external;
local:method($input)
Saxon Verion
implementation 'net.sf.saxon:Saxon-HE:10.2'
implementation 'net.sf.saxon:saxon-xqj:9.1.0.8'
Sample Snippet that i tried
Processor saxon = new Processor(false);
// compile the query
XQueryCompiler compiler = saxon.newXQueryCompiler();
XQueryExecutable exec;
ClassLoader classLoader = MessageProcessor.class.getClassLoader();
exec = compiler.compile(new File(classLoader.getResource("Xquery.xqy").getFile()));
Source src = new StreamSource(new StringReader(Files.readString( Paths.get(ClassLoader.getSystemResource(inputfile.xml").toURI()))));
XdmNode doc = builder.build(src);
// instantiate the query, bind the input and evaluate
XQueryEvaluator query = exec.load();
query.setContextItem(doc);
query.setExternalVariable(new QName("input"), doc.select(child("input")).asNode());
XdmValue result = query.evaluate();
System.out.println(result.itemAt(0).toString());
Irrespective of the java code when i open the xquery in Oxygen XML editor (that uses Saxon-PE XQuery 9.9.1.7 engine) , i get the following validation error.
It is indeed a Saxon optimisation bug. The problem occurs when Saxon attempts to rewrite
for $j in 1 to count($input/bar)
return if ($input/foo[$i]/data = 'A' and $input/baz[$i]/type = 'B')
then <result/>
else ()
as
if ($input/foo[$i]/data = 'A' and $input/baz[$i]/type = 'B')
then for $j in 1 to count($input/bar)
return <result/>
else ()
and you can work around the problem by doing this rewrite "by hand". The purpose of the rewrite is to prevent the unnecessary repeated evaluation of the "if" condition, which is the same each time round the loop.
The reason it's dependent on the "and" condition is that Saxon considers each term of the "and" as a separate candidate for promoting outside the loop, and when it finds that all these terms can be promoted, it reconstitutes the "and" expression from its parts, and the bug occurs during this reconstitution.
It seems like an optimizer bug in Saxon, I reduced your code to
declare function local:test($input as element(input)) as element(output)
{
<output>
<details>
<service>
{
for $i in 1 to count($input/foo)
return
for $j in 1 to count($input/bar)
return if ($input/foo[$i]/data = 'A' and $input/baz[$i]/type = 'B')
then <result/>
else ()
}
</service>
</details>
</output>
};
declare variable $input as element(input) external := <input>
</input>;
local:test($input)
and Saxon HE 10.2 from the command line crashes with
java.lang.NullPointerException
at net.sf.saxon.expr.parser.LoopLifter.markDependencies(LoopLifter.java:168)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:112)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:122)
at net.sf.saxon.expr.parser.LoopLifter.gatherInfo(LoopLifter.java:101)
at net.sf.saxon.expr.parser.LoopLifter.process(LoopLifter.java:51)
at net.sf.saxon.query.XQueryFunction.optimize(XQueryFunction.java:452)
at net.sf.saxon.query.XQueryFunctionLibrary.optimizeGlobalFunctions(XQueryFunctionLibrary.java:327)
at net.sf.saxon.query.QueryModule.optimizeGlobalFunctions(QueryModule.java:1207)
at net.sf.saxon.expr.instruct.Executable.fixupQueryModules(Executable.java:458)
at net.sf.saxon.query.XQueryParser.makeXQueryExpression(XQueryParser.java:177)
at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:568)
at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:630)
at net.sf.saxon.s9api.XQueryCompiler.compile(XQueryCompiler.java:609)
at net.sf.saxon.Query.compileQuery(Query.java:804)
at net.sf.saxon.Query.doQuery(Query.java:317)
at net.sf.saxon.Query.main(Query.java:97)
java.lang.NullPointerException
I think on the command line you can turn off optimization with -opt:0, then the above code doesn't crash.
You might want to raise your bug as an issue on https://saxonica.plan.io/projects/saxon/issues or wait until someone from Saxonica picks it up here.
If I use
for $foo at $i in $input/foo
return
for $bar at $j in $input/bar
Saxon doesn't crash, so perhaps that is a way to rewrite your query as a workaround, although, without data, I am not quite sure I have captured the meaning of your code and that rewrite does the same as your original attempt.
I reproduced it with Martin's test case (thank you, Martin): https://saxonica.plan.io/issues/4765

Custom command result

When invoking a custom command, I noticed that only the logs are displayed. For example, if my Custom Comand script contains a retrun statement return "great custom command", I can't find it in the result. Both in API Java client or shell execution cases.
What can I do to be able to retrieve that result at the end of an execution?
Thanks.
Command definition in service description file:
customCommands ([
"getText" : "getText.groovy"
])
getText.groovy file content:
def text = "great custom command"
println "trying to get a text"
return text
Assuming that you service file contains the following :
customCommands ([
"printA" : {
println "111111"
return "222222"
},
"printB" : "fileB.groovy"
])
And fileB.groovy contains the following code :
println "AAAAAA"
return "BBBBBB"
Then if you run the following command : invoke yourService printA
You will get this :
Invocation results:
1: OK from instance #1..., Result: 222222
invocation completed successfully.
and if you run the following command : invoke yourService printB
You will get this :
Invocation results:
1: OK from instance #1..., Result: AAAAAA
invocation completed successfully.
So if your custom command's implementation is a Groovy closure, then its result is its return value.
And if your custom command's implementation is an external Groovy file, then its result is its last statement output.
HTH,
Tamir.

Concat three or more fields in doctrine

Doctrine query builder allows me to concat two fields only.
class Expr {
// ...
public function concat($x, $y); // Returns Expr\Func
To concatenate 3 fields I use:
$qb->expr()->concat(
'table.field1',
$qb->expr()->concat('table.field2', 'table.field3')
);
And the SQL will be:
CONCAT('table.field1', CONCAT('table.field2', 'table.field3'))
How to get one concat?
When I try to call directly
new Expr\Func('CONCAT', array('table.field1', 'table.field2', 'table.field3'));
Executing query gives me an error
[Syntax Error] line 0, col 237: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got ','
Dumping DQL:
CONCAT('table.field1', 'table.field2', 'table.field3')
Dumping SQL using $qb->getQuery()->getSQL():
[Syntax Error] line 0, col 237: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got ','
CONCAT with variable number of arguments has been introduced in Doctrine ORM version 2.4.0, so you are probably using an older version. I've tested a similar DQL in my project and works as expected.
You should upgrade your Doctrine ORM deps with:
php composer.phar require doctrine/orm:~2.4
Note that (for now) variable arguments are supported only by Expr\Func constructor, but is not supported in Expr::concat method; you still need this syntax:
new Expr\Func('CONCAT', array('table.field1', 'table.field2', 'table.field3'));
UPDATE I've created a PR on GitHub to support multiple arguments in Expr::concat

Resources