# `nautilus-connector`

## Purpose

Database executor layer for Nautilus ORM. Provides the runtime bridge between the SQL rendered by `nautilus-dialect` and real database connections, handling connection-pool management, parameter binding, buffered row streaming, and type conversion.

Supported backends: PostgreSQL, MySQL, SQLite (all via `sqlx`).

## Public API overview

| Type / Trait | Description |
|---|---|
| `Executor` trait | Core abstraction: takes a rendered `Sql` value and returns a `RowStream` |
| `execute_all(executor, sql)` | Convenience helper that collects all rows into a `Vec<Row>` |
| `Row` | Single database row with positional (`get_by_pos`) and named (`get`) access |
| `RowAccess<'row>` trait | Re-exported from `nautilus-core`; the generic access interface used by codegen |
| `RowStream<'conn>` | Type-erased async `Stream<Item = Result<Row>>` shared by all backends |
| `PgRowStream` / `MysqlRowStream` / `SqliteRowStream` | Per-backend type aliases for `RowStream` |
| `PgExecutor` / `MysqlExecutor` / `SqliteExecutor` | Concrete executors wrapping a `sqlx` connection pool |
| `Client<E>` | Combines a `Dialect` and an `Executor`; the entry point for application code |
| `Client::postgres` / `::mysql` / `::sqlite` | Convenience constructors creating both dialect and executor |
| `FromRow` trait | Decode a `Row` into a Rust type (tuple or struct) |
| `ConnectorError` / `ConnectorResult<T>` | Crate-level error type and result alias |

## Usage within the project

- **`nautilus-engine`** depends on this crate and uses `Client<E>` plus `execute_all` to run queries built by the engine.
- **`nautilus-codegen`** generates `FromRow` implementations for user-defined model structs based on the schema.

Typical flow:
```rust
let client = Client::postgres("postgres://…").await?;
let sql = client.dialect().render_select(&select)?;
let rows = execute_all(client.executor(), &sql).await?;
let users: Vec<User> = rows.iter().map(User::from_row).collect::<Result<_>>()?;
```

## Design notes

### Single `RowStream` type
All three backends share one `RowStream<'conn>` struct (`src/row_stream.rs`), a thin `Pin<Box<dyn Stream>>` newtype. The per-backend names (`PgRowStream`, `MysqlRowStream`, `SqliteRowStream`) are type aliases defined in the respective `*_stream.rs` modules for readability at call sites. The lifetime parameter lets pool-backed executors borrow the rendered `Sql` instead of cloning it before wrapping the buffered rows in the uniform stream API.

### Value binding
`bind_value` in each executor module maps every `nautilus_core::Value` variant to the appropriate `sqlx` parameter type. Common notes:
- `DateTime` is bound as ISO 8601 (`%Y-%m-%dT%H:%M:%S%.f`) for all three backends, preserving sub-second precision.
- `Decimal` is bound as its canonical string representation; all three databases accept it for numeric columns.
- `Array` and `Array2D` are serialised to JSON via the shared `utils::value_to_json` helper. PostgreSQL's `Array` arm additionally handles homogeneous typed arrays natively (e.g., `Vec<i64>`), and now rejects typed arrays that contain `NULL` or mixed element variants instead of silently dropping them.

### FromRow macro
Tuple `FromRow` implementations for sizes 1–8 are generated by a single `impl_from_row!` macro that delegates to `SelectColumns::decode` (positional access). Custom struct impls are generated by `nautilus-codegen`.

### Error types
`ConnectorError` wraps the four failure modes (`Connection`, `Database`, `RowDecode`, `Core`). It implements `From<nautilus_core::Error>` for ergonomic use within the engine layer.

### Integration test strategy
SQLite tests run without any external infrastructure and cover the full read/write/stream cycle.  
PostgreSQL and MySQL integration tests mirror the SQLite suite but are marked `#[ignore]` because they require `docker-compose up -d`. Run them explicitly with:
```sh
cargo test -p nautilus-connector -- --include-ignored
```
