Skip to content

Commit 3acc58e

Browse files
committed
sqlitedb: make id, isa and regexp searches fast (port of DID-matlab#229)
NDI's most common searches -- base.id or isa daqsystem, ANDed with base.session_id, sometimes with a regexp -- searched every term over the whole branch and intersected the results, so the session term returned every document of the session and the regexp tested every document. Ported from DID-matlab#229 (dae960b..83a2bda): - _search_doc_ids searches the terms of an AND in rank order: base.id lookups, other terms, base.session_id, then terms that test every value (regexp, contains_string, hasmember, and the brute-force operations). It stops at the first term that matches nothing, and once the result is down to 1000 documents checks later terms against those only (docs.doc_id IN (...), CROSS JOIN order, INDEXED BY doc_data_doc_idx). A brute-force term given candidates loads only those documents. - ORed base.id lookups, nested to any depth, are one query per 1000 ids (_search_base_ids, _base_id_lookup_values). - Unrestricted 'isa' runs its regexp on the distinct superclass lists only, read from doc_data_field_value, instead of on every document. - _ensure_indexes now records whether the doc_data indexes exist (_search_indexes_ready) and leaves a database it cannot write to without them, where it used to fail to open; searches there run as before. DID-matlab now creates the same indexes under the same names. Synthetic database, 100,000 documents / 3M doc_data rows, main -> this: base.id AND session 0.177 s -> 0.0001 s OR of 9 ids AND session 0.181 s -> 0.0006 s isa daqsystem AND session 0.299 s -> 0.027 s isa AND session AND regexp 0.603 s -> 0.027 s Tests: tests/test_search_indexes.py (mirrors DID-matlab's TestSearchIndexes). Bridge: sqlitedb and database entries -> 83a2bda. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dv7SxVR8MCu3MKpUvwwUia
1 parent d84921c commit 3acc58e

4 files changed

Lines changed: 683 additions & 41 deletions

File tree

‎src/did/did_matlab_python_bridge.yaml‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,23 @@ classes:
4040
- name: database
4141
type: class
4242
matlab_path: "+did/database.m"
43-
matlab_last_sync_hash: "bb39399"
43+
matlab_last_sync_hash: "83a2bda"
4444
status: ported
4545
python_path: "did/database.py"
4646
python_class: "Database"
4747
inherits: "abc.ABC"
4848
out_of_sync: false
49+
decision_log: >
50+
DID-matlab#229 (dae960b..83a2bda, 2026-10-24) made database.m's search
51+
fast. search_doc_ids searches the terms of an AND in rank order (base.id
52+
lookups, other terms, base.session_id, then the terms that test every
53+
value) and checks each later term against the documents found so far;
54+
ORed base.id lookups become one query (search_base_ids); and 'isa'
55+
matches its regex against the distinct superclass lists only. All of it
56+
relies on the doc_data indexes that sqlitedb creates (hasSearchIndexes).
57+
In Python the SQL search is SQLiteDB's, not Database's, so the port is in
58+
did/implementations/sqlitedb.py -- see the sqlitedb entry. Nothing
59+
changes in did/database.py.
4960
sync_notes: >
5061
Schema validation was ported on 2026-08-28, closing what had been the
5162
largest capability gap between the two languages. Python previously had

‎src/did/did_matlab_python_bridge_implementations.yaml‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,32 @@ classes:
2929
- name: sqlitedb
3030
type: class
3131
matlab_path: "+did/+implementations/sqlitedb.m"
32-
matlab_last_sync_hash: "bb39399"
32+
matlab_last_sync_hash: "83a2bda"
3333
status: ported
3434
python_path: "did/implementations/sqlitedb.py"
3535
python_class: "SQLiteDB"
3636
inherits_matlab: "did.database"
3737
inherits_python: "Database"
3838
out_of_sync: false
39+
decision_log: >
40+
DID-matlab#229 (dae960b..83a2bda, 2026-10-24): fast id and isa searches,
41+
ported to SQLiteDB (_search_doc_ids, _search_query_head,
42+
_search_base_ids, _query_struct_to_sql_str, _ensure_indexes). MATLAB
43+
adopted the index names Python already created -- doc_data_doc_idx ON
44+
doc_data(doc_idx), doc_data_field_value ON doc_data(field_idx, value) --
45+
so a database touched by both carries one copy of each. Both languages
46+
now add them on open, leave a read-only file without them, and only then
47+
(_search_indexes_ready / hasSearchIndexes) restrict terms to candidates,
48+
collapse ORed base.id lookups, and match 'isa' against the distinct
49+
superclass lists. Three deviations, none of which changes a result:
50+
(1) Python also ranks the operations it brute-forces
51+
(hasanysubfield_*, hassize, partial_struct) with regexp /
52+
contains_string / hasmember as last-in-an-AND, since a brute-force term
53+
loads every document it tests; (2) a brute-force term given candidates
54+
loads only those documents (MATLAB has no brute-force path); (3) Python
55+
applies negation as a complement in Python rather than in SQL, so a
56+
negated term with candidates is the complement within the candidates
57+
rather than within the branch -- the same set once intersected.
3958
sync_notes: >
4059
MATLAB 14439fb (2026-06-12, audit 6.1-3) added a private
4160
escapeSqlLiteral() helper and applied it at the 14 sites where

0 commit comments

Comments
 (0)