|
| 1 | +# To My Agents! |
| 2 | + |
| 3 | +It is my fervent wish that this file guide every AI coding agent working with code in this repository. |
| 4 | + |
| 5 | +## Documentation |
| 6 | + |
| 7 | +Any distilled, agent-facing documentation for this package - how it works |
| 8 | +internally and the rationale behind key design decisions - lives in `docs/`. |
| 9 | +Consult it before non-trivial changes; it is the source of truth from which the |
| 10 | +public manual is distilled. |
| 11 | + |
| 12 | +Two independent worlds - the low-level core and the Explorer (ActiveRow) layer - |
| 13 | +each with sharp edges (lazy execution, accessed-column narrowing, N+1 batching, |
| 14 | +context-detected preprocessor modes). Read `docs/internals/` before touching them. |
| 15 | + |
| 16 | +## Project Overview |
| 17 | + |
| 18 | +**Nette Database** is a database abstraction layer offering two components: |
| 19 | + |
| 20 | +1. **Core** - a PDO wrapper with an advanced SQL preprocessor and parameter |
| 21 | + substitution. |
| 22 | +2. **Explorer** - an ActiveRow layer (inspired by NotORM) with convention-based |
| 23 | + relationships and automatic N+1 prevention. |
| 24 | + |
| 25 | +Supports MySQL, PostgreSQL, SQLite, MS SQL Server, and Oracle. |
| 26 | + |
| 27 | +- **PHP Version**: 8.1 - 8.5 |
| 28 | +- **Package**: `nette/database` |
| 29 | + |
| 30 | +## Essential Commands |
| 31 | + |
| 32 | +```bash |
| 33 | +# Run all tests |
| 34 | +vendor/bin/tester tests -s -C |
| 35 | + |
| 36 | +# Run one test directory / file |
| 37 | +vendor/bin/tester tests/Database/Explorer -s -C |
| 38 | +vendor/bin/tester tests/Database/Explorer/Explorer.basic.phpt -s -C |
| 39 | + |
| 40 | +# Static analysis (PHPStan level 5 + phpstan-nette) |
| 41 | +composer phpstan |
| 42 | +``` |
| 43 | + |
| 44 | +Most tests connect to real MySQL/PostgreSQL/MS SQL servers via |
| 45 | +`@dataProvider databases.ini`. Bring the servers up with the repo's |
| 46 | +`docker-compose.yml` (`docker compose up -d`, wait for `healthy`) before running |
| 47 | +them; a `Connection refused` / `could not find driver` failure means the servers |
| 48 | +aren't up yet, not a broken test. |
| 49 | + |
| 50 | +## Conventions |
| 51 | + |
| 52 | +- Every file starts with `declare(strict_types=1);`; everything typed; single |
| 53 | + quotes unless the string contains an apostrophe; Nette Coding Standard. |
| 54 | +- Use generic annotations for IDE/PHPStan support: `@return Selection<ProductRow>`, |
| 55 | + `@template T of ActiveRow`. Method phpDoc starts with a 3rd-person verb (Returns, |
| 56 | + Formats, Checks); document a param/return only when it adds info beyond the type. |
| 57 | +- Tests are Nette Tester `.phpt` files; use `@dataProvider databases.ini` to run |
| 58 | + against every engine, `test()` / `testException()` with descriptive names, and |
| 59 | + **no comment before `test()`**. Fixtures: `tests/Database/files/{driver}-nette_test1.sql`. |
| 60 | + |
| 61 | +## Working in this repo |
| 62 | + |
| 63 | +- **The Explorer is lazy and self-narrowing.** `accessColumn` is the single seam |
| 64 | + every read passes through; a first query fetches `SELECT *`, later ones narrow to |
| 65 | + the accessed columns (cached), and relations are batched to avoid N+1. The cache |
| 66 | + key even depends on the call-site (`debug_backtrace`) - a real refactor trap. See |
| 67 | + `docs/internals/explorer.md`. |
| 68 | +- **The SQL preprocessor picks its array mode from surrounding SQL context** |
| 69 | + (`?and`/`?set`/`?values`/`?order`/`?list`), so the same array expands differently |
| 70 | + after `WHERE` vs `SET` vs `INSERT`. See `docs/internals/sql-preprocessor.md`. |
| 71 | +- **Nested transactions use a depth counter, not savepoints** - only the outermost |
| 72 | + `transaction()` issues a real BEGIN/COMMIT/ROLLBACK; there is no partial rollback, |
| 73 | + and no retry mechanism (no `$attempts`, no `RetryableException`, no `onRetry`). |
| 74 | + There is no `TypeConverter` class either (DB->PHP conversion is |
| 75 | + `Helpers::normalizeRow`). Don't document designed-but-absent features as present. |
| 76 | +- **Array expansion is a mass-assignment surface.** Passing raw user input as the |
| 77 | + array to `insert`/`update`/`where` lets an attacker set arbitrary columns and |
| 78 | + inject operators/SQL via keys - always whitelist columns first. Full guidance is |
| 79 | + web-manual material. |
| 80 | +- User-facing how-to (Explorer/Selection API, `?`-placeholder reference, NEON |
| 81 | + config, transactions, Reflection API) is manual material and lives in the public |
| 82 | + web docs, not here. |
0 commit comments