Hello,
I noticed I get different result sets with the following queries and I can't understand how they differ from each other.
1) Correct behaviour, returns 3 records
let $file := db:list("Snomed")[matches(.,"MRCM")][3] return for $record in (db:open("Snomed", $file)/csv/record) [position() = (1 to 3)] return $record
2) Unexpected behaviour, returns 21 records
let $file := db:list("Snomed")[matches(.,"MRCM")][3] return for $record in (db:open("Snomed", $file)/csv/record) where position() = (1 to 3) return $record
I have highlighted the one line that differs between them, e.g the first uses the positional predicate in a path expression and the second uses it in a where clause.
Best regards, Kristian Kankainen
On Fri, Jul 23, 2021 at 08:17:39AM +0300, Kristian Kankainen scripsit:
- Unexpected behaviour, returns 21 records
let $file := db:list("Snomed")[matches(.,"MRCM")][3] return for $record in (db:open("Snomed", $file)/csv/record) where position() = (1 to 3) return $record
The let clause returns a sequence of values.
The for clause in the return clause binds $record to a sequence produced by the binding expression, but it's not one long sequence, it's per-sequence-value-by-member-of-$file, so that you start the tuple sequence of the for expression with $record having a sequence value.
The "where" clause then says "I want the first three members of this sequence as the post-where-clause tuple" for _each_ tuple in the tuple sequence produced by the for clause, which is in effect restricting each value of $record in the tuple sequence created by the for clause to the first three values of the sequence returned for each value of $file.
If we knew for sure that all of the sequences bound to $record by the binding expression were at least 3 members in length, we could infer that you have 7 values for "file" to get 21 results, but I don't think we know that.
In your "used a predicate" example, you're constraining the path expression used to construct the binding sequence for the for clause, and the result is a sequence with only three members.
Hi Kristian,
The function position() returns the current context position. The context position is only assigned by certain expressions, such as the filter expression:
(1 to 10)[position() = (1 to 3)]
Before the predicate is evaluated, the current context position will be assigned for each result item of $expr.
If you use position() outside a predicate, it’s usually undefined, and if you call position(), you get an XPDY0002 error in return. The same applies to FLWOR expressions: The following query raises the same error:
for $i in 1 to 10 where position() = (1 to 3) return $i
It’s interesting to read that your second query is not rejected; I assume that the where clause is optimized away at compile time. Feel free to send me the output of the Info View panel, maybe I can see what’s going on.
Best, Christian
- Unexpected behaviour, returns 21 records
let $file := db:list("Snomed")[matches(.,"MRCM")][3] return for $record in (db:open("Snomed", $file)/csv/record) where position() = (1 to 3) return $record
I have highlighted the one line that differs between them, e.g the first uses the positional predicate in a path expression and the second uses it in a where clause.
Best regards, Kristian Kankainen
basex-talk@mailman.uni-konstanz.de