Commit graph

35 commits

Author SHA1 Message Date
Richard Newman
99e7fafd1b Change license to Apache. Fixes #74. 2016-11-22 11:40:37 -08:00
Richard Newman
9d81abace5 Implement ident renaming. Fixes #103. 2016-10-24 20:01:44 -07:00
Nick Alexander
1c83287fcf Pre: Make <avs handle fulltext datoms correctly.
The test would fail because we would have an [a v] pair with a string
value, but we were looking for the fulltext rowid in <avs.  Using
all_datoms correctly looks up the string value, at the cost of crippling
the speed of <avs.
2016-10-14 10:20:43 -07:00
Nick Alexander
60c7db4301 Pre: Make testing consistent by sorting fulltext values before inserting.
This sorts fulltext values inserted in a single transaction, not across
transactions.  This makes the rowids assigned in the fulltext_values
table internally consistent, even as the order of entities and datoms
changes (as the transaction applying algorithm evolves over time).  The
test changes simply make the fulltext values sort easily.

In theory, these fulltext values could be very large, and sorting might
be very expensive.  In practice, we expect values to differ in their
first few characters, so that this is efficient (i.e., proportional to
the number of fulltext values inserted and not their size).
2016-10-14 10:20:43 -07:00
Nick Alexander
d94dfae01b Pre: Add multistep upsert example. 2016-10-14 10:20:43 -07:00
Nick Alexander
3cd64fb4d8 Review comments. 2016-09-30 17:00:27 -07:00
Nick Alexander
611d44fcce Process lookup-refs in batches. Fixes #25.
This uses a common table expression and multiple SQL calls rather than a
temporary table, since transactions with huge numbers of distinct
lookup-refs are likely to be very rare.

We mark lookup-refs with `lookup-ref`, which is a little awkward because
binding `(let [[a v] lookup-ref] ...)` doesn't directly work, but avoids
some ambiguity present in Datomic and DataScript around interpreting
lookup-refs as multiple value lists.  (Which bit the tests in an earlier
version of this patch!)
2016-09-30 16:47:04 -07:00
Richard Newman
360f7622e8 Add handling of simple schemas. Fixes #53. 2016-09-22 15:59:15 -07:00
Richard Newman
1cfbf8498c Introduce js-sqlite as an abstraction wrapper around Sqlite.jsm and promise-sqlite. 2016-09-08 19:11:44 -07:00
Nick Alexander
659c26339c Serialize and de-serialize non-keyword schema values correctly. Fixes #52. 2016-09-07 17:31:30 -07:00
Nick Alexander
362bdb2028 Add :db.fn/retractAttribute and :db.fn/retractEntity. Fixes #46.
There's no distinction made for fulltext attributes, since the values
found by the retractAttributes SELECT are already rowids into the
fulltext_values table and therefore need no additional mapping.
2016-09-06 13:13:20 -07:00
Nick Alexander
cfdce12c1a Pre: Use deftest-db in tests. 2016-09-06 13:13:20 -07:00
Richard Newman
9136ba7425 Basic test for ds/fulltext?. 2016-08-30 18:22:11 -07:00
Nick Alexander
3775c7c773 Start importing places. This is just about profiling for now. 2016-08-30 18:22:10 -07:00
Nick Alexander
71446a3af5 Completely rewrite main transaction logic to be faster.
This is almost complete; it passes the test suite save for retracting
fulltext datoms correctly.

There's a lot to say about this approach, but I don't have time to give
too many details.  The broad outline is as follows.  We collect datoms
to add and retract in a tx_lookup table.  Depending on flags ("search
value" sv and "search value type tag" svalue_type_tag) we "complete" the
tx_lookup table by joining matching datoms.  This allows us to find
datoms that are present (and should not be added as part of the
transaction, or should be retracted as part of the transaction, or
should be replaced as part of the transaction.  We complete the
tx_lookup (in place!) in two separate INSERTs to avoid a quadratic
two-table walk (explain the queries to observe that both INSERTs walk
the lookup table once and then use the datoms indexes to complete the
matching values).

We could simplify the code by using multiple lookup tables, both for the
two cases of search parameters (eav vs. ea) and for the incomplete and
completed rows.  Right now we differentiate the former with NULL checks,
and the latter by incrementing the added0 column.  It performs well
enough, so I haven't tried to understand the performance of separating
these things.

After the tx_lookup table is completed, we build the transaction from
it; and update the datoms materialized view table as well.  Observe the
careful handling of the "search value" sv parameters to handle replacing
:db.cardinality/one datoms.

Finally, we read the processed transaction back to produce to the API.
This is strictly to match the Datomic API; we might make allow to skip
this, since many consumers will not want to stream this over the wire.

Rough timings show the transactor processing a single >50k datom
transaction in about 3.5s, of which less than 0.5s is spent in the
expensive joins.  Further, repeating the processing of the same
transaction is only about 3.5s again!  That's the worst possible for the
joins, since every single inserted datom will already be present in the
database, making the most expensive join match every row.
2016-08-30 18:22:10 -07:00
Nick Alexander
b59c71cb00 Extract datomish.db.debug from test code, in order to use it during development. 2016-08-30 18:22:10 -07:00
Nick Alexander
a1cc372d43 Fix :db.unique/value, which should be per (a, v) pair, not per v-value. 2016-08-30 18:22:10 -07:00
Nick Alexander
b29e5caec0 Implement parts: Make the DB allocate and persist entity IDs.
This implementation is inefficient because each allocated temporary ID
touches the database, but it's enough to allow to re-open DBs.
2016-08-30 18:22:09 -07:00
Nick Alexander
ff9a75ae09 Tag values with value type tags in SQLite. 2016-08-30 18:22:09 -07:00
Nick Alexander
e7e84e0a90 Add d/{ident,entid} for mapping between keyword idents and integer entids. 2016-08-30 18:22:09 -07:00
Nick Alexander
d8c976c3ad Follow-up: split the monolith!
This was a little more tricky than might be expected because the
initialization process uses the transactor to bootstrap the database.
Since Clojure doesn't accept mutually recursive modules, this
necessitated a third module, namely "db-factory", which uses both "db"
and "transact".  While I was here, I started an "api" module, to paper
over the potentially complicated internal module structure for external
consumers.  In time, this "api" module may also grow CLJS-specific JS
transformations.
2016-08-04 17:54:32 -07:00
Nick Alexander
73b155cfdc Follow-up: don't accept schema when creating DB.
This schema was already ignored.
2016-08-04 16:34:48 -07:00
Nick Alexander
44db8116bf Handle nested maps, sequences in maps, and reverse references. 2016-08-04 14:26:20 -07:00
Nick Alexander
d9a8cb0d6a Don't accept user-provided tx values.
This agrees with Datomic.  DataScript allows tx values, possibly to
allow reconstructing DBs from Datom streams, but appears to handle
user-provided tx values in the transactor inconsistently.
2016-08-04 14:26:20 -07:00
Nick Alexander
38545f6efc Add :tx and :txInstant to TxReport; accept :db/tx in transactor; allow to set :db/txInstant.
The implementation of :db/tx is special and may need to change over
time.  We add it as a special ident, with value the current transaction
entity ID, specified per-transaction.  This works well right now but
introduces some (internal) ordering requirements that may need to be
loosened.
2016-08-04 14:26:20 -07:00
Nick Alexander
f25838a1eb Support :db/fulltext true.
Internally, we use SQLite's FTS4 to maintain a fulltext_values table of
unique "text" values.  Fulltext indexed datoms have value v that is the
rowid into fulltext_values.  We manually maintain the map between rowid
and value in the transactor.

For convenience, we expose two views interpolating the real text values
into the datoms structure.
2016-08-04 14:26:20 -07:00
Nick Alexander
13f33a4915 Unify test pattern around "(... -after tx0)". 2016-08-04 14:26:20 -07:00
Nick Alexander
296c9cb436 Bootstrap DB schema; persist and restore schema from materialized views. 2016-08-04 14:26:20 -07:00
Nick Alexander
6a8739bd2f Accept new schema fragments via :db.part/db :db.install/attribute. 2016-08-04 14:26:20 -07:00
Nick Alexander
9497d69b44 Respect :db/unique constraints; test upserts.
This version includes SQLite-level unique indexes; these should never be
needed.  I've included them as a fail-safe while testing; they'll help
us catch errors in the transaction layer above.
2016-08-04 14:26:20 -07:00
Nick Alexander
80742242e2 Fix cljs 2016-08-04 14:26:20 -07:00
Nick Alexander
7a90c43a5a Map valueTypes to SQLite encodings.
In the future, we might add a layer of indirection, hashing values to
avoid duplicating storage, or sorting URLs, or handling fulltext indexed
values differently, or ...
2016-08-04 14:26:20 -07:00
Nick Alexander
43423b7d0a Validate value types. 2016-08-04 14:26:20 -07:00
Nick Alexander
661e7ed123 Allow to add new :db/ident mappings. 2016-08-04 14:26:20 -07:00
Nick Alexander
baec3815b0 Implement transactions. 2016-08-04 14:26:20 -07:00