Stack overflow when transacting :db.type/tupleAttrs with a :db.type/ref attr through :db.fn/call
Nobody has claimed this yet.
- Dominant language
- Clojure
- Stars
- 5.8k
- Forks
- 318
- PR merge metrics
- No merged PRs in 30d
Description
It seems I've run into a stack overflow somewhere deep inside some internals. I'm hoping this might be obvious to someone familiar with the code.
This is the smallest scenariot I've been able to isolate this bug to.
I am modeling an api repository. Providers have a unique name, each provider has a set of services each with a unique name to the provider.
(def conn (d/create-conn {:provider/name {:db/unique :db.unique/identity}
:service/provider {:db/cardinality :db.cardinality/one
:db/valueType :db.type/ref}
:service/name {:db/cardinality :db.cardinality/one}
:service/pk {:db/valueType :db.type/tuple
:db/tupleAttrs [:service/provider :service/name]
:db/unique :db.unique/identity}}))
We'll choose gmail for our test data
(def tx [{:provider/name "googleapis.com"}
{:service/provider [:provider/name "googleapis.com"]
:service/name "gmail/v1"}])
I have another transaction that abstracts this through a :db.fn/call
(def tx-call [[:db.fn/call (fn [_db tx] tx) tx]])
Transacting with the call abstraction works against an empty db
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (out) [#datascript/Datom [1 :provider/name "googleapis.com" 536870913 true]
; (out) #datascript/Datom [2 :service/provider 1 536870913 true]
; (out) #datascript/Datom [2 :service/name "gmail/v1" 536870913 true]
; (out) #datascript/Datom [2 :service/pk [1 "gmail/v1"] 536870913 true]]
Transacting against a non-empty db with duplicate data seems to go fine
(clojure.pprint/pprint (:tx-data (d/transact! conn tx)))
; (out) []
Transacting against a non-empty db with duplicate data overflows
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (err) Execution error (StackOverflowError) at datascript.db/is-attr? (db.cljc:1161).
; (err) null
Transacting against a non-empty db with duplicate data overflows in random spots
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (err) Execution error (StackOverflowError) at datascript.db$reify__3146/compare (db.cljc:543).
; (err) null
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (err) Execution error (StackOverflowError) at datascript.db$reify__3146/compare (db.cljc:543).
; (err) null
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (err) Execution error (StackOverflowError) at datascript.db$reify__3158/compare (db.cljc:558).
; (err) null
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (err) Execution error (StackOverflowError) at datascript.db/is-attr? (db.cljc:1161).
; (err) null
(clojure.pprint/pprint (:tx-data (d/transact! conn tx-call)))
; (err) Execution error (StackOverflowError) at datascript.db.DB/_search (db.cljc:671).
; (err) null
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the transaction sequence in the issue, especially the duplicate transaction through :db.fn/call. Start by tracing the reported paths in db.cljc, including is-attr?, compare, and DB/_search. Done means the duplicate transaction completes without StackOverflowError and preserves the shown empty :tx-data result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- clojure
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100