Add FastFiltersLib, SQLiteFastFilters, and PostgreSQLFastFilters addons#1
Add FastFiltersLib, SQLiteFastFilters, and PostgreSQLFastFilters addons#1dsblank wants to merge 8 commits into
Conversation
FastFiltersLib is a shared GENERAL plugin (load_on_reg=True) that provides SQL-accelerated filter rule overrides via RuleOverride. SQLiteFastFilters and PostgreSQLFastFilters are DATABASE backends that register those overrides on open. Initial rules: IsMale, IsFemale, Disconnected, HasAlternateName. Dialect differences (placeholders, JSON access, regex) are abstracted in fastfilterslib.sql_compat.SQLCompat. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Expands FastFiltersLib from 4 to 19 registered rule overrides: Person overrides (secondary columns, no json_data): - HasUnknownGender, HasOtherGender (gender = 2/3) Person overrides (json_data, fallback to original for blob-data DBs): - NeverMarried (family_list length = 0) - MultipleMarriages (family_list length > 1) Private/public overrides across all nine object types (private is a secondary INTEGER column on every table): - PeoplePrivate, PeoplePublic (person) - FamilyPrivate, EventPrivate, PlacePrivate - CitationPrivate, SourcePrivate, NotePrivate - MediaPrivate, RepoPrivate Place overrides: - HasNoLatOrLon (TRIM(COALESCE(lat/long,''))='') Uses _IsPrivateOverride base class with SQLCompat.true()/false() for dialect-correct boolean comparisons (SQLite: 1/0, PostgreSQL: TRUE/FALSE). Adds PrivateFilterTestsMixin covering all object types, a generalised _commit() helper, and a shared _apply(db, rule, namespace) function. SQLiteFastFilters grows from 35 to 49 passing tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add HasNicknameOverride (Tier 2) that queries primary_name.nick via json_extract; nicks in alternate names or NICKNAME attributes are a documented approximation (false negatives very rare in practice). Remove all blob-data fallback branches (_needs_json_data, the guard checks in prepare(), and the hasattr sentinel in apply_to_one()) since blob databases are no longer supported. Drop the TestJsonDataFallback test class. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, NoBirthdate, NoDeathdate) Add four new SQL-accelerated filter overrides: - MissingParentOverride: persons with no parent families OR a parent family missing a father/mother; uses json_each over parent_family_list joined to the family table's secondary father_handle/mother_handle columns. - HaveChildrenOverride: persons in a family whose child_ref_list is non-empty; uses json_each over family_list joined to family.json_data child_ref_list length. - NoBirthdateOverride / NoDeathdateOverride: persons whose birth/death event has date.sortval == 0 or no event at all; uses a dynamic array-index path via birth_ref_index/death_ref_index secondary columns and a LEFT JOIN to event. A CASE WHEN guard prevents SQLite from evaluating the JSON path when the index is the -1 sentinel (SQLite rejects negative path indices). Add three new SQLCompat helpers: json_each_text(), json_dynamic_array_field(), and json_extract_int(). Add Tier3TestsMixin with setup and correctness tests, plus count-match tests against example.gramps. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HaveAltFamiliesOverride: pure SQL using nested EXISTS — outer json_each over parent_family_list joined to family, inner json_each over child_ref_list filtered to this person's handle, checking frel.value or mrel.value = 2 (ADOPTED). IncompleteNamesOverride: SQL + Python hybrid — SQL covers all primary name cases (blank first_name, empty surname_list, or blank surname entry via json_each); Python post-checks alternate names in apply_to_one(), which is the rare case and avoids a doubly-nested json_each over alternate_names → surname_list. Add json_each_json() to SQLCompat for iterating arrays of JSON objects (uses jsonb_array_elements in PostgreSQL, json_each in SQLite). Add Tier3PlusTestsMixin with correctness tests against a hand-built DB, plus exact-match tests for both rules against example.gramps (2 adopted people; 76 people with incomplete names). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…overrides Sets self.rule.selected_handles instead of self.handles in prepare() for every override whose apply_to_one() does nothing but check set membership. The Gramps filter optimizer detects this attribute on the rule and skips the per-object loop entirely, reducing a filtered scan to a single SQL query + set intersection. IncompleteNamesOverride is intentionally excluded because its apply_to_one() performs additional Python checks on alternate names beyond set membership. Update SQLPathTestsMixin to assert rule.selected_handles rather than override.handles, matching the optimizer protocol. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents all remaining overrideable rules: - Tier 4: ChangedSince and HasTag for all 9 object types - Tier 4a: seven array-count rule families (HasGallery, HasNote, HasLDS, HasAssociation, HasAddress, HasSourceCount, HasRepository) - Tier 4b: type-equality and secondary-column text match (HasRelType, NoteHasType, MatchesTitleSubstringOf) - Tier 5: single JOIN or nested json_each (HasNameType, IsWitness, PersonWithIncompleteEvent, SearchFatherName/Mother/Child, InLatLonNeighborhood) - Tier 5+: not-feasible table with reasons for each rule Updates summary table and implementation order to cover all 27 new rules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…names) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
A simple copy of the dependency to an installation path? |
Summary
Initial filter rules accelerated: `IsMale`, `IsFemale`, `Disconnected`, `HasAlternateName`.
Design notes
Test plan
Run with:
```
cd FastFiltersLib && python -m pytest test/ -q
cd SQLiteFastFilters && python -m pytest test/ -q
```
🤖 Generated with Claude Code