Add support for query parameters, JOINs, SELECT * and three-part table names

This commit is contained in:
Jan Doubravský
2026-06-04 18:25:47 +02:00
parent b044ca43f8
commit 530c2618cf
14 changed files with 511 additions and 106 deletions
+20 -13
View File
@@ -59,11 +59,12 @@ with engine.connect() as conn:
## Komponenty
### 1. SQL Parser
- Detekuje typ dotazu (SELECT / zápis).
- Extrahuje názvy tabulek z FROM a JOIN klauzulí.
- Extrahuje seznam požadovaných sloupců.
- Detekuje `SELECT *` (wildcard) a JOIN — vyhodí `UnsupportedQueryError`.
- Rozhoduje, zda je dotaz obsloužitelný z cache.
- Detekuje typ dotazu (SELECT / zápis); zápisy vyhodí `ReadOnlyError`.
- Extrahuje názvy tabulek z FROM a JOIN klauzulí (podpora více tabulek).
- Mapuje požadované sloupce na tabulky přes aliasy (`columns_by_table`).
- Detekuje `SELECT *` a `alias.*` → tabulka se načte celá (`wildcard_tables`).
- Parsuje přes dialekt `SQLMEM_SQL_DIALECT` (default `tsql`) a renderuje in-memory dotaz do SQLite (stripuje catalog/schema prefixy).
- Parametry (`?` / `:name`) předává beze změny do in-memory SQLite.
### 2. Column Registry
@@ -71,12 +72,12 @@ Modul se **za běhu učí**, jaké sloupce z každé tabulky aplikace potřebuje
**Logika při každém příchozím dotazu:**
1. Parser detekuje `SELECT *` nebo JOIN → vyhodí `UnsupportedQueryError` (není implementováno).
2. Parser extrahuje `(tabulka, sloupce)` z dotazu.
3. Registry provede **union** nově požadovaných sloupců s již známými.
4. Cache Manager zkontroluje, zda cache pro danou tabulku obsahuje všechny potřebné sloupce:
1. Parser extrahuje `(tabulka, sloupce)` pro každou tabulku v dotazu (i přes JOIN).
2. Registry provede **union** nově požadovaných sloupců s již známými.
3. Cache Manager zkontroluje, zda cache pro danou tabulku obsahuje všechny potřebné sloupce:
- **Ano** → dotaz jde přímo do SQLite RAM (cache hit).
- **Ne** → re-fetch tabulky z DB s rozšířenou sadou sloupců → přepíše cache → dotaz do SQLite RAM.
4. `SELECT *` načte celou tabulku a označí ji jako `is_full` → další dotazy na libovolný sloupec jsou cache hit.
**Příklad akumulace sloupců:**
@@ -84,8 +85,8 @@ Modul se **za běhu učí**, jaké sloupce z každé tabulky aplikace potřebuje
Dotaz 1: SELECT A, B FROM T3 → Registry: T3 = {A, B} → fetch T3(A,B) z DB
Dotaz 2: SELECT A, D FROM T3 → Registry: T3 = {A, B, D} → re-fetch T3(A,B,D) z DB
Dotaz 3: SELECT B FROM T3 → cache hit, žádný DB dotaz
Dotaz 4: SELECT * FROM T3 → UnsupportedQueryError (wildcard není podporován)
Dotaz 5: SELECT A FROM T3 JOIN T4 ... → UnsupportedQueryError (JOIN není podporován)
Dotaz 4: SELECT * FROM T3 → full load všech sloupců, tabulka označena is_full
Dotaz 5: SELECT A FROM T3 JOIN T4 ON … → každá tabulka cachována zvlášť, JOIN běží v RAM
```
**Metadata tabulka `_sqlmem_columns`** (uložena v SQLite):
@@ -184,10 +185,16 @@ SQLMEM_DEBUG=true # DEBUG level — podrobný výpis každého dotazu, cache o
---
## Hotové funkce (dříve TODO)
- [x] **Parametrizované dotazy**: `execute(sql, params)` — poziční `?` i pojmenované `:name`.
- [x] **Podpora `SELECT *` (wildcard)**: Načte celou tabulku do cache, označí ji jako `is_full` — další dotazy na libovolný sloupec jsou vždy cache hit bez re-fetch.
- [x] **Podpora JOIN**: Parser extrahuje sloupce z každé joinované tabulky zvlášť, Column Registry je sleduje nezávisle. Cache Manager zajistí, že všechny potřebné tabulky jsou v paměti před spuštěním dotazu.
- [x] **Třídílné názvy tabulek**: `[catalog].[schema].[table]` se cachuje pod base name, in-memory dotaz prefix stripuje.
## TODO — budoucí funkce
- **Podpora `SELECT *` (wildcard)**: Načte celou tabulku do cache, označí ji jako `full` — další dotazy na libovolný sloupec jsou vždy cache hit bez re-fetch.
- **Podpora JOIN**: Parser extrahuje sloupce z každé joinované tabulky zvlášť, Column Registry je sleduje nezávisle. Cache Manager zajistí, že všechny potřebné tabulky jsou v paměti před spuštěním dotazu.
- **TTL na úrovni tabulky**: automatické vypršení cache po nastaveném čase.
---