I'm slightly confused about transactions in xtdb v2. With v1 I can use xt/entity-history to figure out the transactional (not temporal) history of a given document. Moreover, with xt/open-tx-log I can then go from a transaction id to what else happened within the context of the same transaction.
In v2 I can query '(from :xt/txs [*]) which gives me the transactions without the context of what happened in them, and I can't find any meaningful way to go from a document version to the transaction that created it. Am I missing something or that API isn't available (yet)?
Hey @farcaller the trick is joining on _system_from https://play.xtdb.com/?version=2.0.0-beta3&type=sql&txs=W3sic3lzdGVtLXRpbWUiOm51bGwsInR4cyI6IklOU0VSVCBJTlRPIGRvY3MgKF9pZCwgY29sMSkgVkFMVUVTICgxLCAnZm9vJyk7In0seyJ0eHMiOiJJTlNFUlQgSU5UTyBkb2NzIChfaWQsIGNvbDEpIFZBTFVFUyAoMiwgJ2JhcicpOyIsInN5c3RlbS10aW1lIjpudWxsfSx7InR4cyI6IklOU0VSVCBJTlRPIGRvY3MgKF9pZCwgY29sMSkgVkFMVUVTICgzLCAnYmF6Jyk7Iiwic3lzdGVtLXRpbWUiOm51bGx9XQ%3D%3D&query=U0VMRUNUIGRvY3MuX2lkLCBkb2NzLl9zeXN0ZW1fZnJvbSwgeHQudHhzLl9pZCBBUyB0eF9pZCBGUk9NIGRvY3MgSk9JTiB4dC50eHMgT04geHQudHhzLnN5c3RlbV90aW1lID0gZG9jcy5fc3lzdGVtX2Zyb20%3D
ah, I see. So the _system_from is effectively the long-form transaction id and it's unique. Is there anything like xt/open-tx-log to see what else happened during that transaction?
Yes _system_from should always be unique, and we even now disallow transactions happening in the same microsecond (...but that's not relevant for quite some time unless hardware improves dramatically π)
Discovering changes across all tables isn't easy right now - you have to enumerate all the tables (e.g. by querying information_schema.tables) and do a UNION ALL while joining on the _system_from. I would really like to make this simpler but we haven't discussed potential designs in much depth yet. If you need those lookups to be fast though then you may want to consider maintaining your own metadata of tables have been changed by the current transaction (stored in some user-defined table or column, similar to https://discuss.xtdb.com/t/corrections-table-pattern-for-tracking-changes/467).
What's the requirement you're hoping to solve?
I'm just tinkering for now. The conceptual problem I'm solving is "what were the transaction submitted between A and B and which records they affected?"
I have somewhat a "blockchain" proof of concept (a bastardized storage solution that removes all the insanity of a distributed consensus and basically turns it into a transaction log and a computed state). I don't like it and I really want to get rid of all that and looking for options. Insofar v1's xt/open-tx-log does almost what I want (sans tracking the failed transactions which is something I can work around with functions, I think). datomic's log api also seems to do something very similarβI'm not fully sold yet on if I need actual bitemporality for my case as I just need to know "where we are now" and "how we got here".
Thanks for the added context - always useful! Is it a very routine / 'hot path' query to be running in your application? Does it need to be fast? Or just possible?
"just possible" at the moment
and yeah, I know that it's a broad answer. I could do "just possible" with sqlite and lots of code π I'd prefer the db layer to do it for me, though
Bitemporality is particularly useful when the "transactions submitted" and "records affected" are happening in upstream systems, rather than the one that XTDB is underpinning
ah, that actually makes more sense when you put it like that!
Incidentally there was a https://discuss.xtdb.com/t/relate-given-transaction-to-affected-documents/410/4 thread roughly about this already (by @stefcoetzee, no less), so I just updated that with this example too π
A document history in XTQL focused on one table (`store`):
(defn doc-history
"History of document with `:xt/id` of `xt-id` from `store`,
in descending order from most recent to oldest version."
[store xt-id]
(mapv #(into (sorted-map) %)
(pt/q (xt/template
(-> (from ~store
{:bind [{:xt/id ~xt-id}
* xt/valid-from xt/system-from]
:for-valid-time :all-time})
(order-by {:val xt/valid-from
:dir :desc}))))))Should add, where pt/q is defined as:
(defn q [query & opts]
(with-open [node (xtc/start-client http-node-url)]
(xt/q node query opts)))
where xtc is xtdb.client