# `PgRest.QueryPipeline`
[🔗](https://github.com/agoodway/pgrest/blob/v0.1.0/lib/pg_rest/query_pipeline.ex#L1)

Composes query execution through a pipeline:
base_query -> scope -> URL filters -> handle_param -> select -> order -> paginate -> execute -> after_load

# `execute_bulk_create`

```elixir
@spec execute_bulk_create(module(), [map()], map(), keyword()) ::
  {:ok, [map()]} | {:error, non_neg_integer(), Ecto.Changeset.t()}
```

Bulk insert multiple records using Ecto.Multi for individual changeset validation.
Returns {:ok, records} or {:error, index, changeset}.

# `execute_bulk_delete`

```elixir
@spec execute_bulk_delete(module(), map(), map(), keyword()) ::
  {:ok, non_neg_integer()}
  | {:ok, non_neg_integer(), [map()]}
  | {:error, term()}
```

Bulk delete records matching query filters.
Returns {:ok, count} or {:ok, count, records} when returning.

# `execute_bulk_update`

```elixir
@spec execute_bulk_update(module(), map(), map(), map(), keyword()) ::
  {:ok, non_neg_integer()}
  | {:ok, non_neg_integer(), [map()]}
  | {:error, term()}
```

Bulk update records matching query filters.
Returns {:ok, count} or {:ok, count, records} when returning.

# `execute_create`

```elixir
@spec execute_create(module(), map(), map()) ::
  {:ok, map()} | {:error, Ecto.Changeset.t()}
```

Executes a create (POST) pipeline: build changeset, insert, apply after_load.

# `execute_delete`

```elixir
@spec execute_delete(module(), term(), map()) ::
  {:ok, map()} | {:error, :not_found | Ecto.Changeset.t()}
```

Executes a delete (DELETE) pipeline: find by PK within scope, delete.

# `execute_read`

```elixir
@spec execute_read(module(), map(), map(), keyword()) ::
  {:ok, [map()]} | {:ok, [map()], map()} | {:error, term()}
```

Executes a read (GET) pipeline: parse params, apply scope/filters/select/order/pagination, fetch records.

Returns `{:ok, records}` or `{:ok, records, range_info}` when count mode is requested.

# `execute_update`

```elixir
@spec execute_update(module(), term(), map(), map()) ::
  {:ok, map()} | {:error, :not_found | Ecto.Changeset.t()}
```

Executes an update (PATCH) pipeline: find by PK within scope, apply changeset, update.

# `execute_upsert`

```elixir
@spec execute_upsert(module(), map() | [map()], map(), keyword()) ::
  {:ok, non_neg_integer()}
  | {:ok, non_neg_integer(), [map()]}
  | {:error, term()}
```

Upsert records using Ecto's on_conflict support.
Returns {:ok, count} or {:ok, count, records} when returning.

# `normalize_keys`

```elixir
@spec normalize_keys(map(), [atom()]) :: map()
```

Converts string-keyed JSON attrs to atom-keyed maps, filtering to known schema fields.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
