## Release Notes: SeaORM 2.0.0-rc.38

*(since 2.0.0-rc.37)*

### New Features

**`find_both_related()` — required inner join loader** (#2997)

A new `find_both_related()` method returns `Vec<(E::Model, F::Model)>` (both sides non-optional), as a counterpart to the existing `find_also_related()` which returns `Vec<(E::Model, Option<F::Model>)>`. Use this when you know the relation is always populated and want to avoid the `Option` unwrap:

```rust
let results: Vec<(Order, LineItem)> = Order::find()
    .find_both_related(LineItem)
    .all(db)
    .await?;
```

**`set_ne` / `set_ne_and` aliases on `ActiveValue`** (#3040)

Shorter aliases for `set_if_not_equals` and `set_if_not_equals_and`. The long-form names are kept as compatibility aliases:

```rust
// Before
active_model.name.set_if_not_equals("Alice");

// After
active_model.name.set_ne("Alice");
```

**`map_sqlx_*_pool_opts` on `ConnectOptions`** (#2770)

Three new methods to customise the underlying `sqlx::pool::PoolOptions` before the connection pool is created — one per driver:

```rust
ConnectOptions::new(DATABASE_URL)
    .map_sqlx_postgres_pool_opts(|opts| opts.max_connections(20).min_connections(5))
    .to_owned()
```

**`BTreeMap` / `HashMap` support in `TryGetableFromJson`** (#3009)

Map types can now be used directly as model fields when the column holds a JSON object:

```rust
pub struct Model {
    pub id: i32,
    pub metadata: HashMap<String, serde_json::Value>,
}
```

**Inherited visibility in derive macros** (#3029)

`DeriveEntityModel`, `DeriveActiveModel`, `DeriveModel`, and related macros now inherit the `pub(crate)` / `pub(super)` / private visibility of the struct they are applied to, instead of always emitting `pub` items.

### Bug Fixes

**Schema sync: drop unique constraint on PostgreSQL** (#2994)

`DROP INDEX` fails on PostgreSQL for unique indexes created via column-level `UNIQUE` because they are backed by a named constraint, not a standalone index. Schema sync now uses `ALTER TABLE … DROP CONSTRAINT` on PostgreSQL and falls back to `DROP INDEX` on other backends.

**Schema sync: tables in non-default schemas now discovered** (#3016)

`sync()` previously ran schema discovery only against `CURRENT_SCHEMA()`. Entities with `#[sea_orm(schema_name = "other")]` were never found, causing every sync to attempt a redundant `CREATE TABLE`. Discovery now collects all schemas referenced by registered entities and queries each one.

**Nested `PartialModel` null detection for optional fields** (#3039)

A nested `Option<PartialModel>` loaded via a left join could incorrectly fail with `Missing value for column 'id'` when the nested model itself contained `Option<T>` fields. The null check now correctly handles arbitrary `Option` nesting depth.

**`use_transaction` per-migration config was ignored** (#3002)

`exec_with_connection` unconditionally wrapped all PostgreSQL migration operations in a transaction, overriding the per-migration `use_transaction` setting. The macro has been removed and each call site now uses the correct connection type.

**Proc macros failed on long type paths with newlines** (#3031)

`DeriveActiveModelEx` and other derive macros used `.replace(' ', "")` to strip whitespace, which missed newlines in formatted type paths longer than ~50 characters. Replaced with `.split_whitespace().collect()`.

**`TIMESTAMPTZ` conversion in the Postgres proxy driver** (#3004)

`from_sqlx_postgres_row_to_proxy_row` now correctly converts `TIMESTAMPTZ` columns, fixing a panic when using the proxy driver with timestamptz fields.

### Dependency Updates

- `arrow` updated to 58 (#3007)
- `strum` updated to 0.28 (#2993)
