Fork me on GitHub
#datalevin
<
2024-04-07
>
Sasha V. Bogdanov23:04:33

Hi to everybody! explain is crashing 😞 Stacktrace:

:exception #error
 {:cause "Cannot invoke \"java.lang.Number.doubleValue()\" because \"x\" is null",
  :trace [[clojure.lang.RT longCast "RT.java" 1282]
          [datalevin.query$result_explain invokeStatic "query.clj" 1849]
          [datalevin.query$result_explain invoke "query.clj" 1844]
          [datalevin.query$plan_only invokeStatic "query.clj" 1915]
          [datalevin.query$plan_only doInvoke "query.clj" 1905]
          [clojure.lang.RestFn applyTo "RestFn.java" 139]
          [clojure.core$apply invokeStatic "core.clj" 667]
          [clojure.core$apply invoke "core.clj" 662]
          [datalevin.query$explain invokeStatic "query.clj" 1923]
          [datalevin.query$explain doInvoke "query.clj" 1917]
          [clojure.lang.RestFn applyTo "RestFn.java" 139]
          [clojure.core$apply invokeStatic "core.clj" 671]
          [clojure.core$apply invoke "core.clj" 662]
          [datalevin.core$explain invokeStatic "core.clj" 477]
          [datalevin.core$explain doInvoke "core.clj" 422]
          [clojure.lang.RestFn invoke "RestFn.java" 521]
And by the way the query doesn't works as expected also if use d/q That is actually why I tried explain . What can be wrong? I am struggling with this query whole the night. In snippet: (:user/id user): 1 mid: 2 uuids: something like *[*#uuid *"c2c21781-3699-4f6a-949b-32411d0c4013"* #uuid *"213bfbfa-c90a-403b-9b71-6ba5a0a7fc17"]*

Sasha V. Bogdanov23:04:58

Okay! I see in source, that explain is only for remote stores (why nothing about it in docs or change log?). But why it crashing then instead of returning nil? Anyway, what can be wrong with the query? Only what I need i to get all existing :callback entities, who related to certain :user, have certain :callback/message-id attribute and have any :callback/uuid except listed in uuids vector. But it always returns empty sequence. Thank you!

Huahai04:04:42

No, explain works for all modes. You have :run? false, so the query doesn’t run

Huahai04:04:53

Your query could just return nothing for there is no data matching it.

Huahai04:04:44

Try set :run? to true, it might tell you why you’re getting empty results, i.e. you may see one of the :count is zero

Huahai04:04:58

I am curious what condition would trigger this exception you are seeing, doesn't seem to be possible from the code.

Huahai04:04:27

What is your enviornment? Clojure version, java version, os, etc.

Huahai04:04:35

*explain* and *start-time* are bound at the same time, it doesn't seem to be possible for *explain* to be bound and *start-time* is nil, hence it is not possible to get that exception.

Sasha V. Bogdanov11:04:26

Thank you for answers. With {:run? true} there is the same error. Environment: Apple M2 Pro MacOS 14.3.1 (23D60) ▸ lein version Leiningen 2.10.0 on Java 21.0.2 OpenJDK 64-Bit Server VM [org.clojure/clojure "1.11.2"] [datalevin "0.9.4"] :jvm-opts ["--add-opens=java.base/java.nio=ALL-UNNAMED" "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED"] Datalevin connection: (d/conn "/tmp/dlvn" schema {:validate-data? true :closed-schema? true})

Sasha V. Bogdanov11:04:31

With query i can be wrong in something, but if i use just :where [?cb :callback/uuid] i am getting the list of entities and there are some that are suitable for my query. At least it looks alike that for me... Can you take a look once again? Is syntax correct? Especially regarding not clause and looking for :callback/uuid in ?uuids collection...

Huahai15:04:39

You have an impossible error there, I would figure that one out first.

Huahai15:04:40

Java 21 on m2 is not something went through any tests

Huahai15:04:59

Try Java 17?

👌 1
Sasha V. Bogdanov15:04:32

Okay. I will inform you in a hour

Huahai16:04:43

Sorry, I think I have a bug there, it's planning-time is nil

Huahai16:04:07

Right now, I am in a hotel that blocked SSH traffic, so I can't really push code. If you are willing, you can try to fix it yourself, I can tell you which line to change.

👍 1
Huahai16:04:42

As to you query, one of your clauses return 0 results

Huahai16:04:59

after you fix explain, you should see that

👍 1
Sasha V. Bogdanov16:04:35

Oh thank you. Tell me what line to fix then. Possible in PM

Sasha V. Bogdanov16:04:09

Or create issue maybe?

Huahai16:04:47

The fix is an one line change: in query.clj line 1666, replace that line with (do (plan-explain) context)

👍 1
Huahai16:04:01

basically, I forgot to update :planning-time when the planner pre-terminated due to counting to 0 for one of the entity class

👀 1
Huahai16:04:40

after the query graph is built, we already knew the result is empty. this is the case where I missed the call of (plan-explain) to update planning-time, hence the error you saw

Huahai16:04:58

well, after you fix explain, you will not see the query graph, for we are not adding the query graph to the explain result. I can remedy this in the next release.

Huahai16:04:13

in any case, please check your query, your other 3 clauses are returning 0 results. It has nothing to do with the not clause.

👌 1
Sasha V. Bogdanov18:04:47

Interesting moment.... after this fix my query started to return one result. Despite I need two..

Sasha V. Bogdanov20:04:58

How :actual-result-size became 1 when on last step there is :actual-size 2 ?

{:actual-result-size 1,
                                    :execution-time "5.501 ms",
                                    :late-clauses [],
                                    :opt-clauses [[?u :user/id 1] [?cb :callback/user ?u] [?cb :callback/message-id 2]],
                                    :plan {$ [(#datalevin.query.Plan
                                               {:actual-size 1,
                                                :cost 1,
                                                :size 1,
                                                :steps ["Initialize [?u] by :user/id = 1."]}
                                               #datalevin.query.Plan
                                               {:actual-size 2,
                                                :cost 5,
                                                :size 2,
                                                :steps ["Merge ?cb by scanning reverse reference of :callback/user."
                                                        "Merge [?cb] by scanning [:callback/message-id]."]})]},
                                    :planning-time "14.092 ms"}

Sasha V. Bogdanov22:04:52

Hm. I found a solution. I need instead of this

:where
[?u :user/id ?uid]
[?cb :callback/user ?u]
[?cb :callback/message-id ?mid] 
do this
:where
[?cb :callback/user [:user/id ?uid]]
[?cb :callback/message-id ?mid] 
First query returns one callback, second - two as expected. But why?

Huahai22:04:20

Depending on your schema

Huahai22:04:44

These two queries are not equivalent

Huahai22:04:36

You have not shown the schema

Huahai23:04:31

If you think you found a bug, create a minimal reproducible case, and file an issue. Better yet, send a PR of fix

Sasha V. Bogdanov23:04:00

So :user/id and :callback/uuid both are :db.unique/identity . :callback/user is :db.type/ref All another fields are absolutely usual fields

Huahai23:04:05

If you need a query result explained to you, you need to post schema and the data transacted

👌 1