You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Cache table identifier hardening: Added strict validation for cache table names in QueryCache (/^[a-zA-Z_][a-zA-Z0-9_]{0,63}$/) before SQL interpolation. Invalid names now throw CacheException.
Performance Improvements
searchMultiple() merge efficiency: Removed repeated array_merge copying in result aggregation and eliminated duplicate indexExists() checks by tracking validated indices in one pass.
Levenshtein prefilter optimization: In SearchEngine::generateLevenshteinVariations(), query-term bigrams are now computed once per query term instead of once per indexed-term candidate.
Suggestion query roundtrip reduction: Added per-call memoization for count() checks in generateSuggestion() and generateSuggestions() to avoid repeated database checks for identical candidate queries.
Field-weight candidate pool tuning: Reduced default overfetch for field-weight scoring and made candidate sizing configurable:
UTF-8-safe hot paths: Switched key text-processing paths to UTF-8-safe handling:
Snippet extraction in SearchEngine::extractSnippet()
Suggest title normalization/matching in SearchEngine::suggest()
Tokenization/term-position extraction in SqliteStorage
Field-weighted phrase/term matching in SqliteStorage::calculateFieldWeightedScore()
Bug Fixes
Filter operator correctness in storage queries: Fixed inconsistent operator handling between direct columns and JSON fields in SqliteStorage::buildFilterClause() / buildJsonFilterClause(). Added proper support for between and is not null semantics, and corrected in/not in empty-array behavior to avoid invalid SQL or silent filter bypass.
Multi-index ranking in searchMultiple(): Fixed merged result ordering to sort by actual score output (with fallback keys), instead of relying on missing rank/_score keys that could produce non-relevance ordering.
Cache wiring and bypass propagation: Top-level cache config is now passed into storage connection config, and bypass_cache set on SearchQuery options is now propagated from SearchEngine to storage queries.
Tests
Added integration coverage for metadata and direct-column filter operators:
between and is not null regression assertions in tests/Integration/Storage/MetadataFilterTest.php
Added multi-index ranking regression test:
test_search_multiple_indices_sorts_by_score in tests/Integration/Storage/SearchMultipleTest.php
Added query cache integration coverage:
tests/Integration/Storage/QueryCacheIntegrationTest.php verifies top-level cache config wiring and bypass_cache behavior
Added tests/Integration/Storage/FieldWeightCandidateLimitTest.php for default and explicit candidate cap behavior.
Added tests/Integration/Search/Utf8HighlightTest.php for UTF-8 highlight/snippet behavior.
Extended tests/Integration/Storage/QueryCacheIntegrationTest.php with invalid cache table name rejection coverage.