new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Drizzle · PostgreSQL · all subjects

codecs

18 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

What codecs are

Codecs are a driver-aware transform layer that sits between JavaScript values and the database. They solve the problem of different drivers returning and accepting data in different formats for the same column types.

Why codecs are needed: driver differences

Each PostgreSQL driver (node-postgres, postgres-js, pglite, etc.) parses and serializes types differently. Codecs normalize these differences so application code does not have to care which driver is being used.

Why codecs are needed: JSON context

When a column is selected inside a JSON function (like jsonAgg, jsonBuildObject, or relational queries), the database returns values in JSON format which may differ from the regular format. For example, bigint in JSON becomes a number, losing precision. Codecs handle this by casting to text before JSON-ification and then parsing it back.

Codec structure: cast and normalize layers

Codecs have two layers: cast and normalize. Cast operates at the database level by wrapping a column in a SQL ::type cast. Normalize operates at the code level by transforming the raw value into the type JavaScript or the driver expects. Both layers can have separate variants for different query contexts: regular SELECT, inside JSON functions, and as parameters in INSERT/UPDATE.

Codec contexts and method names

Codecs operate across 3 contexts, each with scalar and array variants. Regular SELECT uses cast/castArray and normalize/normalizeArray. Inside JSON (jsonAgg, relational queries) uses castInJson/castArrayInJson and normalizeInJson/normalizeArrayInJson. Params (INSERT/UPDATE) uses castParam/castArrayParam and normalizeParam/normalizeParamArray.

Cast methods in codecs

Cast methods operate at the database SQL level: cast for column in SELECT (example: "col"::text), castArray for array column in SELECT ("col"::text[]), castInJson for column inside JSON functions ("col"::text inside json_agg), castArrayInJson for array column inside JSON, castParam for param placeholder in INSERT/UPDATE/WHERE (example: $1::date), castArrayParam for array param placeholder.

Normalize methods in codecs

Normalize methods operate at the JavaScript level: normalize for SELECT result to JS value (example: "123" → 123n), normalizeArray for SELECT array result to JS array (example: ["123", "456"] → [123n, 456n]), normalizeInJson for SELECT result inside JSON to JS, normalizeArrayInJson for SELECT array inside JSON to JS, normalizeParam for JS value to driver param in INSERT/UPDATE/WHERE (example: { key: "val" } → '{"key":"val"}'), normalizeParamArray for JS array to driver array param (example: [1, 2] → {1,2} as PostgreSQL array literal).

Codecs enabled by default

Yes, codecs are enabled by default. Every driver ships default codecs. When you call drizzle(client), the driver's codecs are automatically used. You do not need to do anything to enable them.

How built-in column types declare codecs

Every built-in PostgreSQL column class declares a codec string identifier via the codec property. For example, PgInteger has codec 'int', PgBigInt53 has codec 'bigint:number', PgBigInt64 has codec 'bigint', PgBigIntString has codec 'bigint:string', PgLineABC has codec 'line', PgLineTuple has codec 'line:tuple'. This identifier is a lookup key into the driver's codec map. If the driver defines transforms for that key, they are applied. If not, the value passes through untouched.

Node-postgres bigint codec example

In node-postgres, the bigint codec identifier defines: normalize as BigInt (transforms SELECT result "123" to 123n), and normalizeArray as arrayCompatNormalize(BigInt) (transforms SELECT array ["123"] to [123n]). The integer codec identifier has no entry in node-postgres because integers do not need transformation.

Overriding codecs for built-in types

Built-in columns (like integer(), bigint(), date(), text(), etc.) have a hardcoded codec string identifier. You cannot change which codec identifier a column uses, but you can change what that codec identifier does by overriding the driver's codec map. Every PostgreSQL driver accepts a codecs option in drizzle(): const db = drizzle(client, { codecs: { "bigint:number": { cast: (name) => sql`${name}::text`, normalize: BigInt } } }).

toDriver/fromDriver vs codecs are separate layers

toDriver and fromDriver on customType and codecs are separate layers. toDriver/fromDriver are per-column instance transforms. Codecs are driver-level transforms and both are applied. On reads, codec normalize is applied first, then fromDriver. On writes, toDriver is applied first, then codec normalizeParam.

Specifying codec in customType with string identifier

When defining a custom column type using customType(), you can specify which codec to use via the codec property with a string value matching one of the PostgreSQL type identifiers (e.g. 'bigint', 'date', 'json', 'text', etc.). Example: const customBigint = customType<{ data: bigint; driverData: string }>({ dataType() { return "bigint"; }, fromDriver(value: string) { return BigInt(Number(value) * 1000); }, codec: "bigint" });

Specifying codec in customType as function

In customType(), the codec property can be a function (config) => string | undefined that dynamically resolves the codec based on the column's config. Example: codec: (config) => { if (!config || config.mode === "bigint") { return "bigint"; } return "bigint:number"; }. This is useful when codec depends on column configuration.

customType codec property options

The codec field in customType accepts three options: A string—one of the PostgreSQL type identifiers (e.g. 'bigint', 'date', 'json', 'text', etc.). A function (config) => string | undefined—dynamically resolve the codec based on the column's config. undefined (default)—no codec, values pass through as-is.

Read flow with codecs and fromDriver

On reads from the database, codec normalize transforms the raw value first, then fromDriver is applied to the result. The order is: database returns value → codec normalize transforms it → fromDriver applies per-column logic → your code receives final value.

Write flow with codecs and toDriver

On writes to the database, toDriver transforms the value first, then codec normalizeParam is applied. The order is: your JavaScript value → toDriver applies per-column logic → codec normalizeParam transforms it → SQL generation adds type cast → database receives value.

Codecs layer added for driver-aware transforms in v1.0

Codecs provide a driver-aware transform layer for normalizing requests and responses to and from the database. They resolve data-mapping inconsistencies between regular select, JSON object, and array contexts.

Give your agent this brain