fluree / core

Fluree releases and public bug reports
0 stars 0 forks source link

Issues with `where`+`optional` and `delete` #47

Closed aaj3f closed 8 months ago

aaj3f commented 8 months ago

Description

It will often be necessary to use where+delete in a transaction and, specifically, include optional bindings in the where clause. For example, I may not know if ex:andrew has any values on multiple properties, schema:name, schema:description, etc., but I do want to delete any values that exist. If I didn't use optional in my where clause, and if one but not both of those properties had values, then not even the property with a value would get retracted

"where": {
  "@id": "ex:andrew",
  "schema:name": "?schemaName",
  "schema:description": "?schemaDescription"
},
"delete": {
  "@id": "ex:andrew",
  "schema:name": "?schemaName",
  "schema:description": "?schemaDescription"
}

If we imagine that ex:andrew had a name but not description, then this where condition would fail and nothing would get bound to either ?schemaName or ?schemaDescription

We want to use optional clauses here so that if one of those values doesn't exist, we don't risk the other one (or more than one) getting dropped by a failed inner join attempt

"where": [
  ["optional",
    { "@id": "ex:andrew", "schema:name": "?schemaName" },
    { "@id": "ex:andrew", "schema:description": "?schemaDescription" },
  ]
],
"delete": {
  "@id": "ex:andrew",
  "schema:name": "?schemaName",
  "schema:description": "?schemaDescription"
}

As @cap10morgan has pointed out, however, this behavior is currently non-functional: https://fluree-internal.slack.com/archives/C04AA19P3FW/p1698773649363289?thread_ts=1698436302.326039&cid=C04AA19P3FW

dpetran commented 8 months ago

As part of this, we should clean up the implementation of retract-triple2 and insert-triple2 to use the where/ helper functions instead of directly accessing the components via their keys.

dpetran commented 8 months ago

This appears to be working with or without the optional clause.

(deftest ^:integration where-optional
  (let [conn   @(fluree/connect {:method :memory})
        ledger @(fluree/create conn "insert-delete")
        db0    (fluree/db ledger)

        db1 @(fluree/stage2 db0 {"@context" "https://ns.flur.ee"
                                 "insert"   [{"@id" "ex:andrew" "schema:name" "Andrew"}]})

        db2  @(fluree/stage2 db1 {"@context" "https://ns.flur.ee"
                                 "where" {"@id" "ex:andrew",
                                          "schema:name" "?schemaName",
                                          "schema:description" "?schemaDescription"},
                                 "delete" {"@id" "ex:andrew",
                                           "schema:name" "?schemaName",
                                           "schema:description" "?schemaDescription"}})

        db3 @(fluree/stage2 db1 {"@context" "https://ns.flur.ee"
                                 "where" [{"@id" "ex:andrew"}
                                          ["optional" {"@id" "ex:andrew",
                                                       "schema:name" "?schemaName",
                                                       "schema:description" "?schemaDescription"}]],
                                 "delete" {"@id" "ex:andrew",
                                           "schema:name" "?schemaName",
                                           "schema:description" "?schemaDescription"}})]
    (is (=  {"@id" "ex:andrew"}
           @(fluree/query db2 {"selectOne" {"ex:andrew" ["*"]}})))
    (is (=  {"@id" "ex:andrew"}
           @(fluree/query db3 {"selectOne" {"ex:andrew" ["*"]}})))))