fix(core): make note_types search filter case-insensitive by phernandez · Pull Request #912 · basicmachines-co/basic-memory · GitHub
Skip to content

fix(core): make note_types search filter case-insensitive - #912

Merged
phernandez merged 1 commit into
mainfrom
fix/note-types-case-insensitive
Jun 8, 2026
Merged

fix(core): make note_types search filter case-insensitive#912
phernandez merged 1 commit into
mainfrom
fix/note-types-case-insensitive

Conversation

@phernandez

Copy link
Copy Markdown
Member

Summary

The search_notes note_types filter was case-sensitive on both the SQLite and Postgres backends, despite the MCP tool documenting it as case-insensitive. The tool lowercases the input ("Chapter" -> "chapter"), but the stored frontmatter type value preserves its original casing ("Chapter"), so the SQL comparison never matched capitalized types. A note with type: Chapter was findable by plain text search but invisible to search_notes(note_types=["Chapter"]).

This fix folds case on both ends of the comparison.

Bugs fixed

  • Bug feat: Add new canvas tool to create json canvas files in obsidian. #14note_types filter is case-sensitive despite documented case-insensitivity (capitalized frontmatter type values were unfindable).
    • SQLite (sqlite_search_repository.py): wrap the column in LOWER(json_extract(metadata, '$.note_type')) and lowercase the parameter values.
    • Postgres (postgres_search_repository.py): replace the JSONB @> containment check (exact-match) with LOWER(metadata->>'note_type') IN (...) and lowercase the parameter values.
    • Values remain parameterized, so the existing SQL-injection protection is unchanged.

Testing

Test came from the integration bug hunt; added under test-int/mcp/test_search_note_types_case_insensitive.py (real DB / ASGI / MCP client, no mocks).

  • uv run pytest test-int/mcp/test_search_note_types_case_insensitive.py -q --no-cov -> 2 passed (SQLite)
  • BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest test-int/mcp/test_search_note_types_case_insensitive.py -q --no-cov -> 2 passed (Postgres)
  • uv run pytest tests/repository/test_search_repository.py test-int/mcp/test_search_integration.py -q --no-cov -> 50 passed (SQLite)
  • BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest tests/repository/test_postgres_search_repository.py tests/repository/test_search_repository.py -q --no-cov -> 47 passed, 12 skipped (Postgres)
  • uv run ruff check (scoped files) / uv run ruff format . / uv run ty check src tests test-int -> all pass

Risk

Low. The change only affects the note_types filter clause. Lowercasing the stored value at comparison time broadens matching to be case-insensitive (the documented behavior); the SQL-injection regression tests for note_types still pass on both backends. No tool signature changed.

🤖 Generated with Claude Code

Bug #14 (integration bug hunt): the search_notes note_types filter was
case-sensitive on both backends. The MCP tool documents note_types as
case-insensitive and lowercases the input ('Chapter' -> 'chapter'), but
the stored frontmatter type preserves its casing ('Chapter'), so the SQL
comparison never matched capitalized types.

Fix folds case on both ends:
- SQLite: LOWER(json_extract(metadata, '$.note_type')) IN (...) with
  lowercased param values.
- Postgres: replace JSONB '@>' containment with
  LOWER(metadata->>'note_type') IN (...) with lowercased param values.

Values stay parameterized, so SQL-injection protection is unchanged.

Adds the regression test from the integration bug hunt under
test-int/mcp/test_search_note_types_case_insensitive.py (real DB/ASGI/MCP
client, no mocks): a capitalized 'type: Chapter' note is now matched by
note_types=['Chapter'], plus a lowercase control.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

@phernandez
phernandez merged commit df7452e into main Jun 8, 2026
25 checks passed
@phernandez
phernandez deleted the fix/note-types-case-insensitive branch June 8, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant