Skip to content

with-transaction problem at datalevin.binding.cpp.CppLMDB/list_count #331

Open
@aldebogdanov

Description

@aldebogdanov

I encountered an interesting bug.

This code:

(ns dtlv-transaction-error.core)

(comment
  (require '[datalevin.core :as d])

  (def schema {:user/username {:db/valueType :db.type/string
                               :db/cardinality :db.cardinality/one
                               :db/unique :db.unique/identity}

               :group/id {:db/valueType :db.type/uuid
                          :db/cardinality :db.cardinality/one
                          :db/unique :db.unique/identity}

               :group/users {:db/valueType :db.type/ref
                             :db/cardinality :db.cardinality/many}

               :rule/group {:db/valueType :db.type/ref
                            :db/cardinality :db.cardinality/one}

               :rule/permission {:db/valueType :db.type/keyword
                                 :db/cardinality :db.cardinality/one}

               :rule/group+permission {:db/valueType :db.type/tuple
                                       :db/cardinality :db.cardinality/one
                                       :db/tupleAttrs [:rule/group :rule/permission]
                                       :db/unique :db.unique/identity}})

  (def cn (d/get-conn "./dtlv" schema {:validate-data? true
                                       :closed-schema? true
                                       :kv-opts {:max-readers 512}}))

  (def init-tx [{:db/id -1
                 :user/username "sasha"}
                {:db/id -2
                 :group/id (random-uuid)
                 :group/users [-1]}
                {:rule/group -2
                 :rule/permission :permission/manager}])

  (d/transact! cn init-tx)

  (d/q '[:find ?g . :in $ ?username
         :where
         [?u :user/username ?username]
         [?g :group/users ?u]
         [?r :rule/group ?g]
         [?r :rule/permission :permission/manager]] (d/db cn) "sasha")

  (d/with-transaction [c cn]
    (d/q '[:find ?g . :in $ ?username
           :where
           [?u :user/username ?username]
           [?g :group/users ?u]
           [?r :rule/group ?g]
           [?r :rule/permission :permission/manager]] (d/db c) "sasha"))
)

Step by step running expressions in comment block. Everything is fine until the last expression that is d/with-transaction. Plain query returns correct 2, but query in transaction fails with:

clj꞉dtlv-transaction-error.core꞉> 
; Execution error (ExceptionInfo) at datalevin.binding.cpp.CppLMDB/list_count (cpp.clj:987).
; Fail to count list: #error {
;  :cause "Key cannot be larger than 511 bytes."
;  :data {:input #datalevin/Indexable [0 5 2 -8 "" 0]}
;  :via
;  [{:type clojure.lang.ExceptionInfo
;    :message "Key cannot be larger than 511 bytes."
;    :data {:input #datalevin/Indexable [0 5 2 -8 "" 0]}
;    :at [datalevin.binding.cpp.Rtx put_key "cpp.clj" 142]}]
;  :trace
;  [[datalevin.binding.cpp.Rtx put_key "cpp.clj" 142]
;   [datalevin.binding.cpp$list_count_STAR_ invokeStatic "cpp.clj" 471]
;   [datalevin.binding.cpp$list_count_STAR_ invoke "cpp.clj" 469]
;   [datalevin.binding.cpp.CppLMDB list_count "cpp.clj" 986]
;   [datalevin.storage.Store av_size "storage.clj" 862]
;   [datalevin.query$count_init_follows$fn__29126 invoke "query.clj" 1760]
;   [clojure.core.reducers$map$fn__12396$fn__12397 invoke "reducers.clj" 134]
;   [clojure.core.protocols$iterator_reduce_BANG_ invokeStatic "protocols.clj" 42]
;   [clojure.core.protocols$iter_reduce invokeStatic "protocol
; s.clj" 52]
;   [clojure.core.protocols$fn__8256 invokeStatic "protocols.clj" 74]
;   [clojure.core.protocols$fn__8256 invoke "protocols.clj" 74]
;   [clojure.core.protocols$fn__8203$G__8198__8216 invoke "protocols.clj" 13]
;   [clojure.core.reducers$reduce invokeStatic "reducers.clj" 46]
;   [clojure.core.reducers$fn__12475 invokeStatic "reducers.clj" 324]
;   [clojure.core.reducers$fn__12475 invoke "reducers.clj" 314]
;   [clojure.core.reducers$fn__12358$G__12353__12369 invoke "reducers.clj" 48]
;   [clojure.core.reducers$folder$reify__12379 coll_fold "reducers.clj" 97]
;   [clojure.core.reducers$fold invokeStatic "reducers.clj" 65]
;   [clojure.core.reducers$fold invoke "reducers.clj" 51]
;   [clojure.core.reducers$fold invokeStatic "reducers.clj" 63]
;   [clojure.core.reducers$fold invoke "reducers.clj" 51]
;   [clojure.core.reducers$fold invokeStatic "reducers.clj" 62]
;   [clojure.core.reducers$fold invoke "reducers.clj" 51]
;   [datalevin.query$count_init_follows invokeStatic "query.clj" 1758]
;   [datalevin.query$count_init_follows i
; nvoke "query.clj" 1754]
;   [datalevin.query$estimate_link_size invokeStatic "query.clj" 1779]
;   [datalevin.query$estimate_link_size invoke "query.clj" 1763]
;   [datalevin.query$estimate_join_size invokeStatic "query.clj" 1792]
;   [datalevin.query$estimate_join_size invoke "query.clj" 1787]
;   [datalevin.query$binary_plan_STAR_ invokeStatic "query.clj" 1829]
;   [datalevin.query$binary_plan_STAR_ invoke "query.clj" 1825]
;   [datalevin.query$binary_plan$fn__29148 invoke "query.clj" 1839]
;   [clojure.core$map$fn__5950$fn__5951 invoke "core.clj" 2759]
;   [clojure.core$filter$fn__5977$fn__5978 invoke "core.clj" 2823]
;   [clojure.lang.PersistentVector reduce "PersistentVector.java" 418]
;   [clojure.core$transduce invokeStatic "core.clj" 7025]
;   [clojure.core$into invokeStatic "core.clj" 7042]
;   [clojure.core$into invoke "core.clj" 7029]
;   [datalevin.query$binary_plan invokeStatic "query.clj" 1836]
;   [datalevin.query$binary_plan invoke "query.clj" 1833]
;   [datalevin.query$plans$fn__29154$fn__29159 invoke "query.clj" 1858]
;   [c
; lojure.core.protocols$iterator_reduce_BANG_ invokeStatic "protocols.clj" 42]
;   [clojure.core.protocols$iter_reduce invokeStatic "protocols.clj" 52]
;   [clojure.core.protocols$fn__8256 invokeStatic "protocols.clj" 74]
;   [clojure.core.protocols$fn__8256 invoke "protocols.clj" 74]
;   [clojure.core.protocols$fn__8203$G__8198__8216 invoke "protocols.clj" 13]
;   [clojure.core$reduce invokeStatic "core.clj" 6965]
;   [clojure.core$reduce invoke "core.clj" 6947]
;   [datalevin.query$plans$fn__29154 invoke "query.clj" 1852]
;   [datalevin.util$map_PLUS_$fn__14723$fn__14724 invoke "util.clj" 631]
;   [clojure.lang.AFn call "AFn.java" 18]
;   [java.util.concurrent.FutureTask run "FutureTask.java" 317]
;   [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1144]
;   [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 642]
;   [java.lang.Thread run "Thread.java" 1583]]}

deps.edn:

{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.12.0"}
        datalevin/datalevin {:mvn/version "0.9.22"}}
 :aliases
 {:run
  {:main-opts ["-m" "dtlv-transaction-error.core"]}
  :build
  {:deps {io.github.clojure/tools.build {:mvn/version "0.10.5"}}
   :ns-default build}}}

Environment:

mbpm2-avbo % ~/dev/dtlv-transaction-error 
▸ uname -a
Darwin mbpm2-avbo.local 24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:54:25 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6020 arm64

mbpm2-avbo % ~/dev/dtlv-transaction-error 
▸ java -version
openjdk version "21.0.6" 2025-01-21 LTS
OpenJDK Runtime Environment Temurin-21.0.6+7 (build 21.0.6+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.6+7 (build 21.0.6+7-LTS, mixed mode, sharing)

mbpm2-avbo % ~/dev/dtlv-transaction-error 
▸ clj --version
Clojure CLI version 1.12.0.1517

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions