# `AshPostgres.Repo`
[🔗](https://github.com/ash-project/ash_postgres/blob/v2.8.0/lib/repo.ex#L5)

Resources that use `AshPostgres.DataLayer` use a `Repo` to access the database.

This repo is a thin wrapper around an `Ecto.Repo`.

You can use `Ecto.Repo`'s `init/2` to configure your repo like normal, but
instead of returning `{:ok, config}`, use `super(config)` to pass the
configuration to the `AshPostgres.Repo` implementation.

## Installed Extensions

To configure your list of installed extensions, define `installed_extensions/0`

Extensions can be a string, representing a standard postgres extension, or a module that implements `AshPostgres.CustomExtension`.
That custom extension will be called to generate migrations that serve a specific purpose.

Extensions that are relevant to ash_postgres:

* "ash-functions" - This isn't really an extension, but it expresses that certain functions
  should be added when generating migrations, to support the `||` and `&&` operators in expressions.
* `"uuid-ossp"` - Sets UUID primary keys defaults in the migration generator
* `"pg_trgm"` - Makes the `AshPostgres.Functions.TrigramSimilarity` function available
* "citext" - Allows case insensitive fields to be used
* `"vector"` - Makes the `AshPostgres.Functions.VectorCosineDistance` function available. See `AshPostgres.Extensions.Vector` for more setup instructions.

```
def installed_extensions() do
  ["pg_trgm", "uuid-ossp", "vector", YourCustomExtension]
end
```

## Transaction Hooks

You can define `on_transaction_begin/1`, which will be invoked whenever a transaction is started for Ash.

This will be invoked with a map containing a `type` key and metadata.

```elixir
%{type: :create, %{resource: YourApp.YourResource, action: :action}}
```

## Additional Repo Configuration

Because an `AshPostgres.Repo` is also an `Ecto.Repo`, it has all of the same callbacks.

In the `c:Ecto.Repo.init/2` callback, you can configure the following additional items:

- `:tenant_migrations_path` - The path where your tenant migrations are stored (only relevant for a multitenant implementation)
- `:snapshots_path` - The path where the resource snapshots for the migration generator are stored.

# `all_tenants`

```elixir
@callback all_tenants() :: [String.t()]
```

Return a list of all schema names (only relevant for a multitenant implementation)

# `create?`

```elixir
@callback create?() :: boolean()
```

Should the repo should be created by `mix ash_postgres.create`?

# `create_schemas_in_migrations?`

```elixir
@callback create_schemas_in_migrations?() :: boolean()
```

Whether or not to create schemas for tables when generating migrations

# `default_constraint_match_type`

```elixir
@callback default_constraint_match_type(
  type :: :custom | :exclusion | :unique | :foreign | :check,
  name :: String.t()
) :: :exact | :prefix | :suffix | {:regex, Regex.t()}
```

Determine how constraint names are matched when generating errors.

This is useful if you are using something like citus that creates generated constraint
names for each node. In that case, for example, you might return a regex that
matches the name plus digits.

# `default_prefix`

```elixir
@callback default_prefix() :: String.t()
```

The default prefix(postgres schema) to use when building queries

# `disable_atomic_actions?`

```elixir
@callback disable_atomic_actions?() :: boolean()
```

Disable atomic actions for this repo

# `disable_expr_error?`

```elixir
@callback disable_expr_error?() :: boolean()
```

Disable expression errors for this repo

# `drop?`

```elixir
@callback drop?() :: boolean()
```

Should the repo should be dropped by `mix ash_postgres.drop`?

# `immutable_expr_error?`

```elixir
@callback immutable_expr_error?() :: boolean()
```

Opt-in to using immutable versions of the expression error functions.

Requires the `AshPostgres.Extensions.ImmutableRaiseError` extension.

# `installed_extensions`

```elixir
@callback installed_extensions() :: [String.t() | module()]
```

Use this to inform the data layer about what extensions are installed

# `migrations_path`

```elixir
@callback migrations_path() :: String.t() | nil
```

The path where your migrations are stored

# `min_pg_version`

```elixir
@callback min_pg_version() :: Version.t()
```

Configure the version of postgres that is being used.

# `on_transaction_begin`

```elixir
@callback on_transaction_begin(reason :: Ash.DataLayer.transaction_reason()) :: term()
```

Use this to inform the data layer about the oldest potential postgres version it will be run on.

Must be an integer greater than or equal to 13.

## Combining with other tools

For things like `Fly.Repo`, where you might need to have more fine grained control over the repo module,
you can use the `define_ecto_repo?: false` option to `use AshPostgres.Repo`.

# `override_migration_type`

```elixir
@callback override_migration_type(atom()) :: atom()
```

Allows overriding a given migration type for *all* fields, for example if you wanted to always use :timestamptz for :utc_datetime fields

# `prefer_transaction?`

```elixir
@callback prefer_transaction?() :: boolean()
```

Whether or not to explicitly start and close a transaction for each action, even if there are no transaction hooks. Defaults to `true`.

# `prefer_transaction_for_atomic_updates?`

```elixir
@callback prefer_transaction_for_atomic_updates?() :: boolean()
```

Whether or not to explicitly start and close a transaction for each atomic update action, even if there are no transaction hooks. Defaults to `false`.

# `tenant_migrations_path`

```elixir
@callback tenant_migrations_path() :: String.t() | nil
```

The path where your tenant migrations are stored (only relevant for a multitenant implementation)

# `use_builtin_uuidv7_function?`

```elixir
@callback use_builtin_uuidv7_function?() :: boolean()
```

Whether or not to use the built-in `uuidv7` function (as opposed to the Ash `uuid_generate_v7` function) for `UUIDv7` fields.

---

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