providerrefactor part1
This commit is contained in:
44
TODO.md
44
TODO.md
@@ -1,7 +1,8 @@
|
||||
# TODO — Database provider reorganization
|
||||
|
||||
Milestones 1–3 are done (provider contract, MSSQL provider, repo reorg).
|
||||
Everything below is outstanding.
|
||||
SQLite provider, native schema, and query translations now exist; store wiring,
|
||||
migrations, lifecycle methods, and parity tests remain outstanding.
|
||||
|
||||
## 1. Convert store modules to the provider API (per area, keep behavior)
|
||||
Replace raw `pool` usage in `src/store/**` with `provider.query()` /
|
||||
@@ -12,11 +13,14 @@ For every module:
|
||||
- [ ] `pool.transaction(); begin; commit; catch rollback` → `provider.transaction(async (tx) => { ... })`
|
||||
- [ ] `result.recordset` → `result.rows`; `result.rowsAffected[0]` → `result.rowsAffected`
|
||||
- [ ] `request.js` helper (`(tx ?? pool).request()`) becomes obsolete — delete when unused
|
||||
- [x] `src/store/runner.js` bridges mixed call sites: converted modules accept a
|
||||
provider runner *or* a legacy mssql Transaction/`pool` (wrapped on the fly)
|
||||
so partially converted callers keep working
|
||||
- [ ] `recordset[0].id` after `OUTPUT INSERTED.id` → keep, but prefer `insertId` where trivial
|
||||
|
||||
Conversion order (bottom-up by dependency):
|
||||
- [ ] `lang`, `tax` (leaf helpers, used by company create)
|
||||
- [ ] `google_auth`
|
||||
- [x] `lang`, `tax` (leaf helpers, used by company create)
|
||||
- [x] `google_auth`
|
||||
- [ ] `companyuser` (resolveCompanyAccess / resolveSelectedCompanyAccess first)
|
||||
- [ ] `company`, `companysetting`
|
||||
- [ ] `customergroup`, `entity`, `entityaddress`, `entitycontact`, `entityhistory`
|
||||
@@ -49,7 +53,7 @@ Conversion order (bottom-up by dependency):
|
||||
- [ ] Document provider contract (JSDoc typedef in `src/providers/provider.js`).
|
||||
|
||||
## 4. better-sqlite3 provider
|
||||
- [ ] Add `src/providers/better-sqlite3/index.js` implementing the same contract:
|
||||
- [x] Add `src/providers/better-sqlite3/index.js` implementing the same contract:
|
||||
- `query()` → prepare + `.all()`/`.get()`/`.run()`; normalize
|
||||
`lastInsertRowid` → `insertId`, `changes` → `rowsAffected`
|
||||
- `transaction(fn)` → `db.transaction()` wrapper (note: better-sqlite3 is sync;
|
||||
@@ -60,11 +64,11 @@ Conversion order (bottom-up by dependency):
|
||||
- `BLOB` handling: return `Buffer` for pic/image/attachment binaries
|
||||
- Error classification: unique → `SQLITE_CONSTRAINT_UNIQUE`, FK → `SQLITE_CONSTRAINT_FOREIGNKEY`
|
||||
- Do NOT close the caller-owned db in the provider; expose `close()`
|
||||
- [ ] `better-sqlite3` as peerDependency (optional) in `package.json`
|
||||
- [ ] package.json exports: `"./providers/better-sqlite3"`
|
||||
- [x] `better-sqlite3` as peerDependency (optional) in `package.json`
|
||||
- [x] package.json exports: `"./providers/better-sqlite3"`
|
||||
|
||||
## 5. SQLite schema (native, not mechanically translated)
|
||||
- [ ] `src/providers/better-sqlite3/schema.js` + migrations:
|
||||
- [x] Native schema in `src/providers/sqlite3/schema.js`:
|
||||
- `INT IDENTITY` → `INTEGER PRIMARY KEY` (rowid)
|
||||
- `NVARCHAR(n)` → `TEXT`; `VARBINARY(MAX)` → `BLOB`
|
||||
- `DATETIME2 DEFAULT SYSUTCDATETIME()` → `TEXT` ISO-8601 UTC
|
||||
@@ -73,11 +77,13 @@ Conversion order (bottom-up by dependency):
|
||||
- `OUTPUT INSERTED...` in queries → `RETURNING ...`
|
||||
- `MERGE companysetting` → `INSERT ... ON CONFLICT ... DO UPDATE`
|
||||
- `[identifier]` brackets → rename or quote (`"number"`)
|
||||
- [ ] **Entity number uniqueness** (MSSQL uses indexed view `v_entity_company_number`):
|
||||
- Add `company_id` column to `entity` (denormalized from customergroup, kept
|
||||
- [ ] Add versioned SQLite migrations around the native schema
|
||||
- [ ] **Entity number uniqueness parity** (MSSQL still uses indexed view
|
||||
`v_entity_company_number`):
|
||||
- [x] SQLite: add `company_id` to `entity` (denormalized from customergroup, kept
|
||||
in sync on insert + customergroup moves) and enforce
|
||||
`CREATE UNIQUE INDEX uq_entity_company_number ON entity(company_id, number) WHERE number IS NOT NULL`
|
||||
- Add the equivalent MSSQL migration for parity; remove the indexed view
|
||||
- [ ] Add the equivalent MSSQL migration for parity; remove the indexed view
|
||||
- [ ] Versioned migrations via `meta` table (already exists) instead of pure
|
||||
`IF NOT EXISTS` scripts for both providers
|
||||
- [ ] Implement `initialize()` (migrations) and `purge()` (drop tables, FK-order)
|
||||
@@ -85,17 +91,21 @@ Conversion order (bottom-up by dependency):
|
||||
drop order — replicate)
|
||||
|
||||
## 6. SQL translation per area (SQLite queries)
|
||||
- [ ] `TOP 1` → `LIMIT 1` (mind: TOP without ORDER BY — keep identical ordering)
|
||||
- [ ] `OUTER APPLY (SELECT TOP 1 ...)` (article/category first-pic joins) →
|
||||
- [x] Add all 32 modules under `src/providers/sqlite3/queries/`, preserving the
|
||||
MSSQL query modules' named-export API (plus SQLite number helpers)
|
||||
- [x] `TOP 1` → `LIMIT 1` (mind: TOP without ORDER BY — keep identical ordering)
|
||||
- [x] `OUTER APPLY (SELECT TOP 1 ...)` (article/category first-pic joins) →
|
||||
correlated subquery or `JOIN` on min(sort,id)
|
||||
- [ ] `FOR JSON PATH` (getBySku, listSearchIndex, listExport, getTreeForCompany) →
|
||||
build JSON in JS from plain rows (preferred: keeps providers dumb)
|
||||
- [ ] Recursive CTEs (`SEARCH_ARTICLES`, `RESOLVE_ARTICLE_ACCESS_BY_SKU`,
|
||||
- [x] `FOR JSON PATH` queries → SQLite JSON1 aggregation with shapes compatible
|
||||
with the current store parsers (building JSON in JS remains a future cleanup)
|
||||
- [x] Recursive CTEs (`SEARCH_ARTICLES`, `RESOLVE_ARTICLE_ACCESS_BY_SKU`,
|
||||
`GET_CATEGORY_TREE_FLAT`) → SQLite `WITH RECURSIVE` (mostly compatible)
|
||||
- [ ] `ISNULL` / `COALESCE` differences; `FLOAT` vs `REAL`
|
||||
- [ ] Case-insensitive comparisons relying on MSSQL default collation
|
||||
- [x] `ISNULL` / `COALESCE` differences; `FLOAT` vs `REAL`
|
||||
- [x] Case-insensitive comparisons relying on MSSQL default collation
|
||||
(e.g. name-uniqueness checks) → `COLLATE NOCASE` in SQLite schema or
|
||||
explicit `LOWER()` in both dialects
|
||||
- [x] Compile all 212 complete SQLite query exports against an in-memory native
|
||||
schema (zero syntax/schema errors)
|
||||
|
||||
## 7. Contract / parity tests
|
||||
- [ ] Test harness that runs the identical suite against both providers
|
||||
|
||||
Reference in New Issue
Block a user