Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Map context item (.) bug: effectiveBooleanValue error filtering maps with not() #3873

Open
joewiz opened this issue May 5, 2021 · 5 comments

Comments

@joewiz
Copy link
Member

joewiz commented May 5, 2021

Describe the bug

Issue #3240 described and PR #3496 fixed a number of errors thrown in eXist when the context item (.) is a map, array, or function. We've got another one, so far affecting only maps in certain conditions:

When using a predicate to filter sequence of maps, wrapping the filter expression in a function that involves the context item's effective boolean value causes an error to be thrown.

xquery version "3.1";

let $words :=
    (
        map {
            "word": "foo",
            "rhymes-with-boo": true()
        },
        map {
            "word": "bar",
            "rhymes-with-boo": false()
        }
    )
return
    $words[not(.?rhymes-with-boo)]?word

This query should return bar, and BaseX and Saxon return the expected result, but eXist throws an effectiveBooleanValue error:

err:FORG0006 effectiveBooleanValue: first item of '(true, false)' is not a node, and sequence length > 1 [at line 15, column 12]

The error location points to the not() function. This suggests that eXist is treating the query as if the context item is the sequence on the left-hand side of the predicate, instead of the item being

Expected behavior

eXist should not throw this incorrect error.

To Reproduce

Building on the tests in https://github.com/eXist-db/exist/pull/3496/files#diff-6f2de4fc23f42984d074ae40eb4f18bb63715b592ad8d08b699010a7ed1e7460:

xquery version "3.1";

module namespace filter-function-items-in-context="http://exist-db.org/xquery/test/filter-function-items-in-context";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare variable $filter-function-items-in-context:maps := ( map { "id": 1 }, map { "id": 2, "foo": 3 } );

declare
    %test:assertEmpty
function filter-function-items-in-context:effective-boolean-value() {
    $filter-function-items-in-context:maps[not(.?id)]
};

This returns the following result:

<testsuite package="http://exist-db.org/xquery/test/filter-function-items-in-context"
    timestamp="2021-05-05T00:09:31.915-04:00" tests="1" failures="0" errors="1" pending="0"
    time="PT0.001S">
    <testcase name="filter-function-items-in-context:effective-boolean-value"
        class="filter-function-items-in-context:effective-boolean-value">
        <error type="err:FORG0006"
            message="Invalid argument type. effectiveBooleanValue: first item of '(1, 2)' is not a node, and sequence length &gt; 1"
        />
    </testcase>
</testsuite>

Context (please always complete the following information):

  • OS: macOS 11.3
  • eXist-db version: eXist 5.3.0-SNAPSHOT 5a850aa 20210502161939
  • Java Version: 1.8.0_292 (Liberica OpenJDK)

Additional context

  • How is eXist-db installed? built from source
  • Any custom changes in e.g. conf.xml? no
@line-o
Copy link
Member

line-o commented May 5, 2021

I believe this is a duplicate of the issue with not() in a predicate.

@line-o
Copy link
Member

line-o commented May 5, 2021

To test this hypothesis:

  • create a function that wraps the call to not()
  • use this wrapper in predicate

@line-o
Copy link
Member

line-o commented May 5, 2021

related #2159
(I can't find the issue where I posted about the wrapped not function)

@line-o
Copy link
Member

line-o commented May 5, 2021

Here is what I meant

  • I added a positive case to the maps and
  • wrapped the call to not
declare variable $local:maps := (
  map { "id": 1 },
  map { "id": 2, "foo": 3 }, 
  map{ 1: 0 }
);

declare function local:not($a) {
    not($a)
};

declare function local:effective-boolean-value() {
    $local:maps[local:not(.?id)]
};

local:effective-boolean-value()

@joewiz
Copy link
Member Author

joewiz commented May 5, 2021

@line-o I think I found the issue where you posted about the not() function: #2308 (comment) (and where you developed the test suite committed in PR #2370). I agree that this is more about eXist's handling of not() than a particular issue with maps, and that it's a dupe of #2308, where @wolfgangmm shared this key insight about the underlying problem with not() in eXist:

eXist handles fn:not in a particular way by trying to evaluate it as a set operation. Obviously this approach is wrongly applied here. A naive fix would likely result in many expressions becoming slower by an order of magnitude, so we need to be careful here. We'll keep this issue open, but fixing will take considerable time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants