This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-12
Channels
- # aleph (3)
- # announcements (15)
- # architecture (6)
- # babashka (35)
- # babashka-sci-dev (10)
- # biff (5)
- # calva (9)
- # cherry (1)
- # cider (44)
- # clj-kondo (31)
- # cljfx (1)
- # clojure (108)
- # clojure-europe (32)
- # clojure-norway (12)
- # clojurescript (15)
- # conjure (3)
- # cursive (8)
- # datahike (1)
- # datalevin (19)
- # datascript (1)
- # datomic (59)
- # emacs (4)
- # graphql (3)
- # jobs (1)
- # luminus (6)
- # meander (9)
- # membrane (45)
- # nbb (67)
- # off-topic (16)
- # portal (3)
- # remote-jobs (1)
- # scittle (8)
- # shadow-cljs (46)
- # test-check (7)
- # tools-deps (5)
- # vim (63)
- # web-security (11)
- # xtdb (15)
how do i find the schema for a transaction? (the the ent that has :txInstant and some other keys...) i just don't know what keys it has and i can't find documentation on it. i can't even find examples of how to add a doc string to a transaction
i found these
{:db/cardinality {:db/id 35},
:db/doc "Attribute whose value is a :db.type/instant. A :db/txInstant is recorded automatically with every transaction.",
:db/id 50,
:db/ident :db/txInstant,
:db/index true,
:db/valueType {:db/id 25}}
{:db/doc "Partition used to store data about transactions. Transaction data always includes a :db/txInstant which is the transaction's timestamp, and can be extended to store other information at transaction granularity.",
:db/id 3,
:db/ident :db.part/tx}
is it the case that a transaction can just have any data on it so long as there is a schema for it in in DB?
A transaction is an entity. Just like any entity, it can be in the E or V slot of any datom
They are special only in that their ids must be in the tx partition, only they may have :db/txInstant assertions (this assertion is what makes it a transaction), and :db/txInstant cannot decrease in value relative to the previous transaction.
Datomic docs often say something like ”the variable is bound”, eg. wrt rule bindings. What exactly does bound mean in this context?
I’ve been reading about rules and required rule bindings and I’m not quite sure I understand the description
Every variable mentioned in a clause is bound (i.e. some set of values was assigned to it) at the end of the clause’s evaluation
because some clauses produce the bindings (e.g. by pattern-matching, by unifying other already-bound values, by executing a function and binding the result, etc)
So if I specify that a particular rule argument is required, I should have a where clause (either before or after) which refers to it?
by “required” I assume you mean “must be bound”, i.e. this rule declaration syntax (rule-name [?must ?bind ?these] ?maybe-unbound)
?
Related question: what exactly does unify mean? Again, it’s one of those words used often, yet I dont quite grasp it
:in ?a
; bound by args: ?a
:where
; bound: ?a
[?a ?b ?c]
; bound: ?a ?b ?c
[?c ?d]
; bound: ?a ?b ?c ?d
(myrule ?x ?y)
; bound: ?a ?b ?c ?d ?x ?y
[(myfn ?x) ?g]
; bound: ?a ?b ?c ?d ?x ?y ?g
What happens if you first refer to a rule, which has a required variable, and then provide a normal where clause which binds the variable? Does it first ”execute” the latter clause and then ”execute” the rule?
I wouldn’t rely on clause reordering though. the point of that syntax is to make sure that the rule doesn’t evaluate in an inefficient order
clauses are generally not reordered, so selectivity of the first clause is very important
inside a rule, it can be less predictable than in a :where
how the rule was “invoked” in various queries, so someone may have left the vars for the first clauses unbound, causing a potentially large result set.
a smarter system would reorder the clause evaluation in the rule based on selectivity or cardinality information, but datomic does not do that
re: unification, imagine that you have a table, and each variable in the query is a column
when you “unify” vars, you discard entire rows where a clause is not satisfied for the corresponding vars mentioned
ah, right
oh and thanks a lot for explaining this stuff, I should really read a prolog book or something 🙂
e.g. [?a 1] if ?a is unbound gives you a table of all (unique) ?a where the attribute slot is 1.
[(+ ?a 1) ?b] if ?b is unbound just adds a column ?b with +1 every ?a value for every row
the reason I'm reading about this (and asking silly questions) is that earlier today I was looking at some code in review where it had a where clause with a) first a few rules which required some bound variables and b) later a very lax normal clauses which bound those variables. I was a bit confused because I had understood that the variables should be bound before the rule is invoked but apparently the code worked. but later we noticed that with a larger db size it was also quite slow. does this make any sense?
(I should really test this in a repl instead of just pondering about it..)
yep. It sounds like it pushed down the rule, but only as far as needed to get something bound, and you just got lucky that it was enough to satisfy the requirements?
yeah, that would explain the poor performance. It couldn't satisfy the requirements of the rules, until it found the clauses it could bind (returning a huge set of data) which it finally ran through the rules
are you aware of these? https://docs.datomic.com/cloud/best.html#datomic-query
although reading the datomic documentation sometimes feels a bit like reading clojure spec docs: it all makes sense but first you have to do the work to really understand it yourself 🙂
in any case, thanks a lot for helping me
Regarding dev-local, can I simply copy and paste the the db.log and log.idx files under the system and database directories to move a database from one computer to another? Any potential issues with that approach?
I'm trying to make a view to display all the entities i deleted in a transaction. i've been looking over the docs and at the datomic API, and i'm not very sure how to do this. i've used filtered DBs before, but i need 1 or 2 extra steps and i'm not sure what they are. right now i just have the entity that is the tx where the deletions occured. i need to get the IDs of the things that were deleted. this is what i have so far
(let [t (->> (d/entity db entity-id)
(d/entity-db)
(d/basis-t))]
(->> (d/tx-range (d/log conn) nil t)
first
:data
(map (fn [[e a v _]]
[e a v]))))
the datoms i'm getting back look like they are from the start of my DB creation
(let [t (->> (d/entity db entity-id)
(d/entity-db)
(d/basis-t))]
(->> (d/tx-range (d/log conn) nil t)
;;first
(take-last 5)
(mapcat :data)
(map (fn [[e a v _]]
[e a v]))))
if i do the above i get datoms that seem to have the right dates, but they don't look like my deleted data
(d/tx-range (d/log conn) (dec t) (inc t))
this seems to give me the deleted data. it's still a mess to look at cus there are no idents for attributes.
can i do a pull on this data somehow?
-----------------------SOLVED---------------------
(let [t (->> (d/entity db entity-id)
(d/entity-db)
(d/basis-t))
deleted-ids (->>
(d/tx-range (d/log conn) t (inc t))
(mapcat :data)
(map (fn [[e a v _]]
e))
(into #{})
vec)]
(d/pull-many
(d/as-of db (dec t))
'[*]
deleted-ids))
yey!