nodeSolidServer / node-solid-server

Solid server on top of the file-system in NodeJS
https://solidproject.org/for-developers/pod-server
Other
1.78k stars 299 forks source link

NSS can't PATCH booleans represented as "true" or "false" #1468

Open Vinnl opened 4 years ago

Vinnl commented 4 years ago

Issue can be seen in action here (view the Network requests in your browser's DevTools): https://codesandbox.io/s/inruptsolid-client-js-sandbox-forked-xyvbg?file=/src/index.ts

GET https://vincent-test.inrupt.net/public/booleantest.ttl:

@prefix : <#>.
@prefix n0: <http://example.com/>.

:me n0:testbool true.

Alright, now let's try to turn that true to false:

PATCH to https://vincent-test.inrupt.net/public/booleantest.ttl with request body:

DELETE DATA {<https://vincent-test.inrupt.net/public/booleantest.ttl#me> <http://example.com/testbool> "true"^^<http://www.w3.org/2001/XMLSchema#boolean>.}; INSERT DATA {<https://vincent-test.inrupt.net/public/booleantest.ttl#me> <http://example.com/testbool> "false"^^<http://www.w3.org/2001/XMLSchema#boolean>.};

Response: 409 Conflict:

The patch could not be applied. Could not find to delete: <https://vincent-test.inrupt.net/public/booleantest.ttl#me> <http://example.com/testbool> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> .

Trying it again with this request body does work (i.e. "true" replaced by "1"):

DELETE DATA {<https://vincent-test.inrupt.net/public/booleantest.ttl#me> <http://example.com/testbool> "1"^^<http://www.w3.org/2001/XMLSchema#boolean>.}; INSERT DATA {<https://vincent-test.inrupt.net/public/booleantest.ttl#me> <http://example.com/testbool> "false"^^<http://www.w3.org/2001/XMLSchema#boolean>.};
michielbdejong commented 4 years ago

I think it's probably the mismatch between "true" and "true"^^<http://www.w3.org/2001/XMLSchema#boolean>?

michielbdejong commented 4 years ago

The error message says it's looking for a triple

<https://vincent-test.inrupt.net/public/booleantest.ttl#me> <http://example.com/testbool> "true"^^<http://www.w3.org/2001/XMLSchema#boolean>

and can't find that.

What you can do is find where that error is thrown, and log all the statements from the store, to see which triples it does have in store.

Vinnl commented 4 years ago

@michielbdejong Aren't the two equivalent? true being syntactic sugar for an RDF literal with the value true and of type boolean, and "true"^^<http://www.w3.org/2001/XMLSchema#boolean> explicitly being an RDF literal with the value true and of type boolean?

What do you mean by the store? The data at https://vincent-test.inrupt.net/public/booleantest.ttl? Because the GET already shows me what triples are in there, right? (i.e. :me n0:testbool true., which as far as I can see is exactly the Triple that the error message says it can't find.)

RubenVerborgh commented 4 years ago

FYI I noticed that rdflib.js parses true as 1 (the number) but the long version of the literal as "true" (the untyped string). So definitely already a bug there.

JorgWieme commented 4 years ago

Incorrect handling of INSERT PATCH, I tried to save true but false was saved. Currently I am using the solid.community server with version solid-server/5.5.2. I am trying to save that boolean with query-ldflex.

When performing following code:

import data from "@solid/query-ldflex";
import {namedNode, literal} from "rdflib";

data["https://jowieme.solid.community/private/workflowProfile.ttl#user"]["wasteInfoShownToUser"]
    .add(literal(true, namedNode('http://www.w3.org/2001/XMLSchema#boolean')));

Where the PATCH payload is:

INSERT DATA {
  <https://jowieme.solid.community/private/workflowProfile.ttl#user>
  <https://example.org/ns/example#wasteInfoShownToUser>
  "true"^^<http://www.w3.org/2001/XMLSchema#boolean>.
}

My https://jowieme.solid.community/private/workflowProfile.ttl looks like this:

@prefix : <#>.
@prefix XML: <http://www.w3.org/2001/XMLSchema#>.
@prefix ex: <https://example.org/ns/example#>.

:user ex:wasteInfoShownToUser false.

Meanwhile doing the same but with 1 instead of true:

import data from "@solid/query-ldflex";
import {namedNode, literal} from "rdflib";

data["https://jowieme.solid.community/private/workflowProfile.ttl#user"]["wasteInfoShownToUser"]
    .add(literal(1, namedNode('http://www.w3.org/2001/XMLSchema#boolean')));

The PATCH:

INSERT DATA {
  <https://jowieme.solid.community/private/workflowProfile.ttl#user>
  <https://example.org/ns/example#wasteInfoShownToUser>
   "1"^^<http://www.w3.org/2001/XMLSchema#boolean>.
}

Resulting into:

@prefix : <#>.
@prefix XML: <http://www.w3.org/2001/XMLSchema#>.
@prefix ex: <https://example.org/ns/example#>.

:user ex:wasteInfoShownToUser true.
megoth commented 1 year ago

Just wanted to chime in that I've come across this bug as well. I suspect the problem is how rdflib.js handles boolean values, and that true and "true"^^<http://www.w3.org/2001/XMLSchema#boolean> are handled differently.

This means that given the following Turtle resource:

@prefix : <#>.
@prefix todo: <https://icanhasweb.net/vocab/todo.ttl#>.

:defaultList
    a todo:List;
    todo:task :task-1, :task-2;
    todo:name "Todo list".

:task-1 a todo:Task; todo:description "Foo"; todo:done true.

:task-2 a todo:Task; todo:description "Bar".

The following SPARQL UPDATE will fail:

INSERT DATA { 
    <https://solidweb.me/megoth-capgemini/todo.ttl#task-2> <https://icanhasweb.net/vocab/todo.ttl#done> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> . 
};
DELETE DATA { 
    <https://solidweb.me/megoth-capgemini/todo.ttl#task-2> <https://icanhasweb.net/vocab/todo.ttl#done> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> . 
}

While the following SPARQL UPDATE will succeed:

INSERT DATA { 
    <https://solidweb.me/megoth-capgemini/todo.ttl#task-2> <https://icanhasweb.net/vocab/todo.ttl#done> false . 
};
DELETE DATA { 
    <https://solidweb.me/megoth-capgemini/todo.ttl#task-2> <https://icanhasweb.net/vocab/todo.ttl#done> true . 
}

This bug has forced me to design my vocabulary to not use boolean values.

timbl commented 1 year ago

Let's look at the spec for the XSD Boolean type.

It says that the lexical space of the type is any of 0, 1, false, true. There are two ways of representing each of the two boolean states. I guess for some, Boolean is a subset of Integer...

So @RubenVerborgh RDFlib is correct in parsing the turtle keyword true as "1"^^xsd:Boolean.

For example here you see it using the "0" "1" form when generating a literal.

Obviously in the quadstore we need to do some canonicalization, or queries will fail.

RubenVerborgh commented 1 year ago

The authoritative spec here is the Turtle specification.

So @RubenVerborgh RDFlib is correct in parsing the turtle keyword true as "1"^^xsd:Boolean.

It is not, because the Turtle spec says:

The literal has a lexical form of the true or false, depending on which matched the input, and a datatype of xsd:boolean.

Therefore, "1"^^xsd:boolean and "0"^^xsd:boolean are not valid parsings of true and false in Turtle, despite their equivalence under the XSD spec.