# Casing

> snake_case or camelCase models, mapped at the edge of the database.

Source: https://bettersupabase.com/docs/concepts/casing

Set `casing` in the config. A config without it uses `'snake'`, which keeps
database names as they are; `better-supabase init` writes `casing: "camel"`
unless you pass `--casing snake`.

```ts
export default defineConfig({ casing: "camel" });
```

With `'camel'`, models, filters, includes and returned rows use camelCase.
The mapping happens in the query itself, not in a post-processing pass:

```ts
await db.customers.findMany({ select: ["id", "organizationId"] });
// GET /customers?select=id,organizationId:organization_id
```

PostgREST renames the columns in its response, so rows need no transform and
nested includes keep their shape.

## Per-table overrides [#per-table-overrides]

```ts
export default defineConfig({
  casing: "camel",
  tables: { legacy_events: { casing: "snake" } },
});
```

## Function results [#function-results]

`db.$rpc` returns rows of a table (`returns setof customers`) and records
(`returns table (customer_id uuid, total numeric)`) in the configured casing,
with the same codecs as reads. `gen` records which functions need it in the
metadata, so other results, such as a scalar, `json` or `jsonb`, come back
as Postgres sent them:

```ts
const rows = await db
  .$rpc("customers_by_status", { p_status: "lead" })
  .orThrow();
rows[0].organizationId;
```

`returns` validates the decoded value, so a schema for the cased row works.
`{ raw: true }` skips the decoding and returns database names, typed as
`unknown`. PostgREST sends `int8` as a JSON number in function results, so
values above 2^53 lose precision before a `bigint` codec sees them; cast
them to `text` in the function when they can be that large.

## What stays in database names [#what-stays-in-database-names]

* Constraint names (`onConflict: 'customers_organization_id_kvk_key'`).
* Plugin config columns (`softDelete: { column: 'archived_at' }`): these name
  database columns, and the generated flags hold the app names.
* Raw SQL, RPC argument names and the keys inside `json` results.

Error details keep the database name in `constraint` and `columns`, since
they come from Postgres.