Example of XQuery expression evaluation is not sequential - xquery

I am looking for an example which shows that XQuery expression evaluation is not sequential. It is always mentioned when comparing the functional nature of XQuery with procedural languages.
E.g. in XQuery, 2nd edition, in the section below:
The FLWOR expression with its for clause is similar to loops in
procedural languages such as C. However, one key difference is that in
XQuery, because it is a functional language, the iterations are
considered to be in no particular order. They do not necessarily occur
sequentially, one after the other.

In general, the language is designed so that you can't tell what the order of evaluation is, which makes it difficult to demonstrate that it's not what you expect. To observe the actual order of evaluation, you need to do something that has side-effects, which generally means straying outside the language specification and using vendor extensions. For example you could use the EXPath file module and issue calls to file:append-text(), and then examine the order of entries added to the external text file.
Of course, it wouldn't prove anything if the entries in the file are in exactly the order you expect. Query processors aren't going to use a non-obvious order of execution just for the fun of it. They will only do so if there is something to be gained by changing the order. Saxon, for example, will delay evaluating variables until they are used, and will lift expressions out of a loop if it can. But you then have the problem, that if you use functions with side-effects like file:append-text() to observe this behaviour, Saxon might detect that your code has side-effects and suppress the optimization.

In some implementations you can experience that the order of the result in more complex FLOWR expressions is arbitrary, for instance taking an example from Priscilla Walmsley's book http://www.datypic.com/books/xquery/ a grouping of item elements ('order.xml' in http://www.datypic.com/books/xquery/chapter01.html) with
<order num="00299432" date="2015-09-15" cust="0221A">
<item dept="WMN" num="557" quantity="1" color="navy"/>
<item dept="ACC" num="563" quantity="1"/>
<item dept="ACC" num="443" quantity="2"/>
<item dept="MEN" num="784" quantity="1" color="white"/>
<item dept="MEN" num="784" quantity="1" color="gray"/>
<item dept="WMN" num="557" quantity="1" color="black"/>
</order>
in Saxon 9.8 HE with the code (7.11 in http://www.datypic.com/books/xquery/chapter07.html)
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'xml';
declare option output:indent 'yes';
for $item in //item
group by $d:= $item/#dept, $n:= $item/#num
return <group dept="{$d}" num="{$n}" count="{count($item)}"/>
gives the output
<?xml version="1.0" encoding="UTF-8"?>
<group dept="ACC" num="563" count="1"/>
<group dept="MEN" num="784" count="2"/>
<group dept="WMN" num="557" count="2"/>
<group dept="ACC" num="443" count="1"/>
while for instance with BaseX you might get a different output order (I think based on the input order of items if I remember it correctly) for the group elements, for instance in BaseX 9 I get
<group dept="WMN" num="557" count="2"/>
<group dept="ACC" num="563" count="1"/>
<group dept="ACC" num="443" count="1"/>
<group dept="MEN" num="784" count="2"/>

Related

How to put dynamic date filter in TDE?

In "context" how to use date function? I want to keep the triples only for last 10 days of the doc ingested in ML.
<template xmlns="http://marklogic.com/xdmp/tde">
<context>/MedlineCitation[createDate > ( fn:currentDateTime() - xs:dayTimeDuration('P10D')]</context>
<triples>
<triple>
<subject>
<val>sem:iri(concat(ForeName,' ',LastName))</val>
</subject>
<predicate>
<val>sem:iri('authored')</val>
</predicate>
<object>
<val>xs:string(../../ArticleTitle)</val>
</object>
</triple>
</triples>
</template>
The function is fn:current-dateTime(), not fn:currentDateTime(), and you are missing the ending ):
/MedlineCitation[createDate > ( fn:current-dateTime() - xs:dayTimeDuration('P10D') )]
However, after correcting the code you will then find that it returns XDMP-UNINDEXABLEPATH.
There are restrictions and limitations for what are allowable expressions and functions for an indexable path expression. See: https://docs.marklogic.com/guide/xquery/xpath#id_18473
For a list of Functions Callable in Predicate Expressions, see:
https://docs.marklogic.com/guide/xquery/xpath#id_51541
A Query Base View that calculates date logic at runtime might be a more appropriate means of implementing the dynamic date filter and integrating with your TDE.

XQuery cardinality error on outputting results to text file

Using XQuery 3.1 (under eXistDB 4.4), I have a function which returns a serialized output of 710 delimited rows like these:
MS609-0001~ok~0001~1r~Deposition~De_Manso_Sanctarum_Puellarum_1~self~1245-05-27~Arnald_Garnier_MSP-AU~self
MS609-0002~ok~0002~1r~Deposition~De_Manso_Sanctarum_Puellarum_1~MS609-0001~1245-05-27~Guilhem_de_Rosengue_MSP-AU~MS609-0001
MS609-0003~ok~0003~1r~Deposition~De_Manso_Sanctarum_Puellarum_1~MS609-0001~1245-05-27~Hugo_de_Mamiros_MSP-AU~MS609-0001
I get the above serialized results in another function that should store it in the directory /db/apps/deheresi/documents as a flatfile depositions.txt
let $x := schedule:deposition-textfile()
return xmldb:store(concat($globalvar:URIdb,"documents"), "deposition.txt", $x)
But when I execute the xmldb:store action, it returns an error:
Description: err:XPTY0004 checking function parameter 3
in call xmldb:store(untyped-value-check[xs:string,
concat("/db/apps/deheresi/", "documents")], "depositions.txt", $x):
XPTY0004: The actual cardinality for parameter 3 does not
match the cardinality declared in the function's signature:
xmldb:store($collection-uri as xs:string,
$resource-name as xs:string?,
$contents as item()) xs:string?.
Expected cardinality: exactly one, got 710.
How do I get these serialized results into the text file?
Thanks in advance.
UPDATE: I tried wrapping the serialized output in <result> and that fixes the problem of cardinality, BUT it writes the <result> element to the file as plain text:
<result>MS609-0001~ok~0001~1r~Deposition~De_Manso_Sanctarum_Puellarum_1~self~1245-05-27~Arnald_Garnier_MSP-AU~self
MS609-0002~ok~0002~1r~Deposition~De_Manso_Sanctarum_Puellarum_1~MS609-0001~1245-05-27~Guilhem_de_Rosengue_MSP-AU~MS609-0001
MS609-0003~ok~0003~1r~Deposition~De_Manso_Sanctarum_Puellarum_1~MS609-0001~1245-05-27~Hugo_de_Mamiros_MSP-AU~MS609-0001</result>
Even if I add:
declare option exist:serialize "method=text";
The error message seems quite clear. The return type of schedule:deposition-textfile() is not acceptable to xmldb:store(). You want a single string, not 710.
Either change the return type of your function, or search the xQuery function documentation for xmldb:store to find a suitable alternative for your returntype.
I don't know the function you are calling, but perhaps you should use string-join() to combine the 710 strings into one, with a newline separator.

Is a string value "yes/no" allowed as value for the indent parameter of the serialize function?

Using BaseX 8.6 the following use of the serialize function with a map as the second argument works fine:
serialize(<root><foo><bar>test</bar></foo></root>, map { 'indent' : 'yes'})
and outputs the indented code
<root>
<foo>
<bar>test</bar>
</foo>
</root>
However, when I try to run the same code with Saxon 9.7 or AltovaXML Spy they don't compile the query and complain about map { 'indent' : 'yes'} not being a boolean value but a string. https://www.w3.org/TR/xpath-functions-31/#func-serialize defines
indent xs:boolean? true() means "yes", false() means "no"
so I am not quite sure whether that allows only a boolean and is meant to explain its meaning in relation to the serialization values of yes/no or whether it also means using yes or no is allowed.
In BaseX, the map argument was added before it was integrated in the XQFO 3.1 specification. Back then, the most obvious choice was to use the syntax for output declarations in the query prolog (in which only strings can be used for values of serialization parameters). – The new official syntax will be made available in a future version of BaseX.

DCG, right-recursion and how to express it clearly

I have read a lot of the suggested questions but I am still stuck with my learning problem right now, I am trying to write a simple Lisp s-expression parser and I cannot figure out how to tackle the recursive nature of an s-expression without tying my brain into knots!
Here is what I have, the input is a list of tokenised terms from the source file from my lexer module which works fine: (GNU Prolog by the way)
lisp_term(T) -->
(
null(T)
;
token(T)
;
sexp_open(_), lisp_term(T2), sexp_close(_), {T = lnode(T2)}
).
lisp_term(T) --> [], {T=end}.
sexp_open(Pos) --> [popen(Pos)].
sexp_close(Pos) --> [pclose(Pos)].
token(token(Pos,Token)) --> [token(Pos,Token)].
null(null(Pos1)) --> [popen(Pos1), pclose(_)].
and here is my calling code...
lisplex('../test.lisp',X),
lexpp(X),
phrase(lisp_term(A), X, Y),
format("Result: ~w~n", [A]),
format("Remainder: ~w~n", [Y]).
the output from the lexer is a list like this, the source: "(hello)"
[popen(pos(1,1)),token(pos(1,2),[h,e,l,l,o]),pclose(pos(1,7))]
I continually get tied up trying to figure out how to deal with an expression like:
(defun whizzle (a1 b2)
(munge (* 10 a1) (+ b2 a1)))
That is, how to deal generally with turning the lexer stream into a parse tree. You can see that my DCG rules are attempting to do that.
I would really appreciate some help and pointers to good stuff to read or advice on how to better understand dealing with right-recursive situations. I have been teaching myself Prolog for a few months now and love it to bits BUT I am stuck on being able to proceed with my understanding of DCG-s and situations like this.
Thanks,
Sean.
I think you are missing the list ! Try (untested)
lisp_term(T) --> token(T).
lisp_term(lnode(T)) -->
sexp_open(_), lisp_list(T), sexp_close(_).
lisp_list([H|T]) -->
lisp_term(H), lisp_list(T).
lisp_list([]) --> [].
Then take a look to Lisprolog, available from Markus Triska' page.

How to use Vector in Flex?

I am trying to use the new Vector class introduced in Flash 10. Tried compiling the code using mxmlc but am getting this error message:
Error: Type was not found or was not a compile-time constant: Vector.
public var selectedRoutes:Vector.<Route>;
^
What could be the problem?
What is the general consensus about the viability of using this feature?
Can you do introspection of the Vector with describeType and get the type the Vector contains at runtime?
At a guess, you are compiling for FP9 instead of FP10, or perhaps against an older version of the SDK. Make sure everything is up to date.
The Vector type is more performant than using an Array and casting entries to the desired type.
I can't help feeling that they had to hack the compiler to make it work though. The generic-style syntax is valid only for the Vector type, and not a general language feature, which sucks.
If you need the performance or like the type-safety of using the Vector class then it's worth it.
I don't know what describeType gives you back on a Vector type. Why don't you give it a whirl?
I tried a describeType on a Vector declaration:
trace(describeType(Vector.<Route>))
The result was:
<type name="AS3.vec::Vector.<components::Route>" base="Class" isDynamic="true" isFinal="false" isStatic="true"> <extendsClass type="Class"/> <extendsClass type="Object"/> <accessor name="prototype" access="readonly" type="" declaredBy="Class"/> <factory type="AS3.vec::Vector.<components::Route>"> <extendsClass type="AS3.vec::Vector.<>"/> <extendsClass type="Object"/> <accessor name="fixed" access="readwrite" type="Boolean" declaredBy="AS3.vec::Vector.<>"/> <accessor name="length" access="readwrite" type="uint" declaredBy="AS3.vec::Vector.<>"/> </factory></type>
So, yes, it does provide the type information. You can pick it out from either the type tag's name or from the factory tag's type.
You should open flex-config.xml and change the target player:
target-player>10.0.0
That will solve the problem.

Resources