Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
524de2f
TML-3061: specify target codec descriptor foundations
tensordreams Jul 23, 2026
e7cbb55
TML-3061: dispatch PostgreSQL descriptor protocol
tensordreams Jul 23, 2026
22e8cce
feat(postgres): add target codec descriptor protocol
tensordreams Jul 23, 2026
aae794f
TML-3061: re-dispatch PostgreSQL descriptor protocol
tensordreams Jul 23, 2026
3dccb91
fix(postgres): tighten codec descriptor protocol
tensordreams Jul 23, 2026
510f6a0
TML-3061: record PostgreSQL descriptor protocol dispatch
tensordreams Jul 23, 2026
91ebcd7
TML-3061: dispatch SQLite descriptor protocol
tensordreams Jul 23, 2026
7c23104
feat(sqlite): add target codec descriptor protocol
tensordreams Jul 23, 2026
2dd8638
TML-3061: record SQLite descriptor protocol dispatch
tensordreams Jul 23, 2026
8879426
TML-3061: dispatch PostgreSQL built-in adoption
tensordreams Jul 23, 2026
1a72ff5
feat(postgres): adopt built-in codec descriptors
tensordreams Jul 23, 2026
d003ef1
TML-3061: record PostgreSQL built-in adoption dispatch
tensordreams Jul 23, 2026
122ec75
TML-3061: dispatch SQLite built-in adoption
tensordreams Jul 23, 2026
a5c8eb4
feat(sqlite): adopt built-in codec descriptors
tensordreams Jul 23, 2026
bce9f7c
TML-3061: record SQLite built-in adoption dispatch
tensordreams Jul 23, 2026
60a21bd
TML-3061: sequence extension adoption before validation
tensordreams Jul 23, 2026
e398f53
TML-3061: dispatch PostgreSQL extension adoption
tensordreams Jul 23, 2026
1f7ed29
feat(extensions): adopt PostgreSQL codec descriptors
tensordreams Jul 23, 2026
948d5e0
TML-3061: record PostgreSQL extension adoption dispatch
tensordreams Jul 23, 2026
13f31bb
TML-3061: dispatch PostgreSQL adapter composition
tensordreams Jul 23, 2026
678099a
feat(postgres): compose target codec registries
tensordreams Jul 23, 2026
99d5c7c
TML-3061: correct PostgreSQL registry injection
tensordreams Jul 23, 2026
27ee7c2
fix(postgres): make codec registry injection coherent
tensordreams Jul 23, 2026
ec7df34
TML-3061: record PostgreSQL adapter composition dispatch
tensordreams Jul 23, 2026
868c383
TML-3061: dispatch SQLite adapter composition
tensordreams Jul 23, 2026
8efcb47
feat(sqlite): compose target codec registries
tensordreams Jul 23, 2026
d09d775
TML-3061: record SQLite adapter composition dispatch
tensordreams Jul 23, 2026
ccfe744
TML-3061: dispatch authoring docs and upgrade instructions
tensordreams Jul 23, 2026
656a33e
TML-3061: repair extension replay fixtures
tensordreams Jul 23, 2026
7ed1c12
TML-3061: supply pgvector fixture dimensions
tensordreams Jul 23, 2026
bc8618b
TML-3061: document target codec descriptor authoring
tensordreams Jul 23, 2026
34cbd5c
TML-3061: correct codec authoring examples
tensordreams Jul 23, 2026
bec2a73
TML-3061: correct descriptor examples and dimensions
tensordreams Jul 23, 2026
a432fd6
TML-3061: record authoring docs dispatch
tensordreams Jul 23, 2026
56fb506
TML-3061: dispatch preservation audit
tensordreams Jul 23, 2026
2b31f0e
TML-3061: adapt SQLite composition to extensions rename
tensordreams Jul 23, 2026
40aa64e
TML-3061: align PostgreSQL emitted descriptor tests
tensordreams Jul 23, 2026
a1a9c03
TML-3061: make extension codec types declaration-portable
tensordreams Jul 23, 2026
80eb633
TML-3061: record preservation audit dispatch
tensordreams Jul 23, 2026
6690e02
test(sqlite): build the symbol-codec stub on a SQLite codec registry
tensordreams Jul 27, 2026
310318b
TML-3061: use ifDefined for conditional codec ref properties
tensordreams Jul 27, 2026
33f0ffc
docs(codecs): state the case-study import convention
tensordreams Jul 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 216 additions & 26 deletions docs/reference/codec-authoring-guide.md

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions packages/2-sql/2-authoring/contract-ts/src/contract-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,17 @@ import type { UnionToIntersection } from './authoring-type-utils';
import type { AttributeStageIdFieldNames, FieldStateOf, ScalarFieldBuilder } from './contract-dsl';
import type { EnumTypeHandle } from './enum-type';

export type PublicCodecTypes<CodecTypes extends Record<string, { readonly output: unknown }>> = {
readonly [CodecId in keyof CodecTypes]: Pick<
CodecTypes[CodecId],
Extract<keyof CodecTypes[CodecId], 'input' | 'output' | 'traits'>
>;
};

export type ExtractCodecTypesFromPack<P> = P extends {
__codecTypes?: infer C extends Record<string, { output: unknown }>;
__codecTypes?: infer C extends Record<string, { readonly output: unknown }>;
}
? C
? PublicCodecTypes<C>
: Record<string, never>;

export type MergeExtensionCodecTypes<Packs extends Record<string, unknown>> = UnionToIntersection<
Expand Down
1 change: 1 addition & 0 deletions packages/3-extensions/arktype-json/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@prisma-next/framework-components": "workspace:0.16.0",
"@prisma-next/sql-relational-core": "workspace:0.16.0",
"@prisma-next/sql-runtime": "workspace:0.16.0",
"@prisma-next/target-postgres": "workspace:0.16.0",
"@standard-schema/spec": "^1.1.0",
"arktype": "~2.2.2"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@

import type { JsonValue } from '@prisma-next/contract/types';
import {
type AnyCodecDescriptor,
type CodecCallContext,
CodecDescriptorImpl,
CodecImpl,
type CodecInstanceContext,
type ColumnHelperFor,
type ColumnSpec,
column,
} from '@prisma-next/framework-components/codec';
import { isRuntimeError, runtimeError } from '@prisma-next/framework-components/runtime';
import type { ProjectionExpr } from '@prisma-next/sql-relational-core/ast';
import {
definePostgresCodecs,
PostgresCodecDescriptor,
} from '@prisma-next/target-postgres/codec-descriptor';
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { ArkErrors, ark, type Type, type } from 'arktype';

Expand Down Expand Up @@ -208,7 +211,13 @@ const arktypeJsonParamsSchema = type({

const ARKTYPE_JSON_META = { db: { sql: { postgres: { nativeType: 'jsonb' } } } } as const;

export class ArktypeJsonDescriptor extends CodecDescriptorImpl<ArktypeJsonTypeParams> {
export class ArktypeJsonDescriptor extends PostgresCodecDescriptor<ArktypeJsonTypeParams> {
protected override nativeType(): string {
return ARKTYPE_JSON_NATIVE_TYPE;
}
protected override jsonProjection(expression: ProjectionExpr): ProjectionExpr {
return expression;
}
override readonly codecId = ARKTYPE_JSON_CODEC_ID;
override readonly traits = ['equality'] as const;
override readonly targetTypes = [ARKTYPE_JSON_NATIVE_TYPE] as const;
Expand Down Expand Up @@ -284,4 +293,4 @@ arktypeJsonColumn satisfies ColumnHelperFor<ArktypeJsonDescriptor>;
*/
export type ArktypeJsonCodec<TInferred> = ArktypeJsonCodecClass<TInferred>;

export const codecDescriptors: readonly AnyCodecDescriptor[] = [arktypeJsonDescriptor];
export const codecDescriptors = definePostgresCodecs([arktypeJsonDescriptor]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { CodecInstanceContext } from '@prisma-next/framework-components/codec';
import type { AnyPostgresCodecDescriptor } from '@prisma-next/target-postgres/codec-descriptor';
import { type } from 'arktype';
import { expectTypeOf, test } from 'vitest';
import {
type ArktypeJsonCodecClass,
type ArktypeJsonDescriptor,
arktypeJsonColumn,
arktypeJsonDescriptor,
codecDescriptors,
} from '../src/core/arktype-json-codec';

test('arktype-json canonical descriptors are PostgreSQL target descriptors', () => {
expectTypeOf(codecDescriptors).toExtend<readonly AnyPostgresCodecDescriptor[]>();
expectTypeOf<(typeof codecDescriptors)[number]>().toEqualTypeOf<ArktypeJsonDescriptor>();
});

test('arktype-json preserves descriptor erasure and column-site schema inference', () => {
const schema = type({ name: 'string', price: 'number' });
const column = arktypeJsonColumn(schema);

expectTypeOf(arktypeJsonDescriptor.factory(column.typeParams)).toEqualTypeOf<
(ctx: CodecInstanceContext) => ArktypeJsonCodecClass<unknown>
>();
expectTypeOf(column.codecFactory).toEqualTypeOf<
(ctx: CodecInstanceContext) => ArktypeJsonCodecClass<{ name: string; price: number }>
>();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { JsonValue } from '@prisma-next/contract/types';
import type { CodecRef } from '@prisma-next/framework-components/codec';
import { ColumnRef } from '@prisma-next/sql-relational-core/ast';
import { type } from 'arktype';
import { describe, expect, it } from 'vitest';
import {
arktypeJsonColumn,
arktypeJsonDescriptor,
codecDescriptors,
} from '../src/core/arktype-json-codec';
import { arktypeJsonCodecRegistry } from '../src/core/registry';
import { arktypeJsonExtensionDescriptor } from '../src/exports/control';
import { arktypeJsonRuntimeDescriptor } from '../src/exports/runtime';

describe('arktype-json PostgreSQL codec descriptor adoption', () => {
it('uses one target descriptor instance across canonical, registry, runtime, and control contributions', () => {
expect(codecDescriptors).toEqual([arktypeJsonDescriptor]);
expect(
codecDescriptors.every((descriptor) => descriptor.descriptorKind === 'postgres-codec'),
).toBe(true);
expect([...arktypeJsonCodecRegistry.values()]).toEqual(codecDescriptors);
expect(arktypeJsonRuntimeDescriptor.codecs()).toEqual(codecDescriptors);
expect(arktypeJsonRuntimeDescriptor.types?.codecTypes?.codecDescriptors).toEqual(
codecDescriptors,
);
expect(arktypeJsonExtensionDescriptor.types?.codecTypes?.codecDescriptors).toEqual(
codecDescriptors,
);
});

it('preserves jsonb native type, identity projection, and structured JSON behavior', () => {
const schema = type({ name: 'string', price: 'number' });
const column = arktypeJsonColumn(schema);
const ref: CodecRef = {
codecId: arktypeJsonDescriptor.codecId,
typeParams: {
expression: column.typeParams.expression,
jsonIr: column.typeParams.jsonIr as JsonValue,
},
};
const expression = ColumnRef.of('products', 'details');

expect(arktypeJsonDescriptor.nativeTypeFor(ref)).toBe('jsonb');
expect(arktypeJsonDescriptor.meta?.db?.sql?.postgres?.nativeType).toBe('jsonb');
expect(arktypeJsonDescriptor.projectJson(expression, ref)).toBe(expression);

const codec = column.codecFactory({ name: 'details' });
const value = { name: 'Widget', price: 9.99 };
expect(codec.encodeJson(value)).toEqual(value);
expect(codec.decodeJson(value)).toEqual(value);
});
});
2 changes: 1 addition & 1 deletion packages/3-extensions/pgvector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@prisma-next/sql-relational-core": "workspace:0.16.0",
"@prisma-next/sql-runtime": "workspace:0.16.0",
"@prisma-next/sql-schema-ir": "workspace:0.16.0",
"@prisma-next/target-postgres": "workspace:0.16.0",
"@prisma-next/utils": "workspace:0.16.0",
"@standard-schema/spec": "^1.1.0",
"arktype": "^2.2.2"
Expand All @@ -36,7 +37,6 @@
"@prisma-next/operations": "workspace:0.16.0",
"@prisma-next/postgres": "workspace:0.16.0",
"@prisma-next/sql-contract-ts": "workspace:0.16.0",
"@prisma-next/target-postgres": "workspace:0.16.0",
"@prisma-next/test-utils": "workspace:0.16.0",
"@prisma-next/tsconfig": "workspace:0.16.0",
"@prisma-next/tsdown": "workspace:0.16.0",
Expand Down
19 changes: 14 additions & 5 deletions packages/3-extensions/pgvector/src/core/codecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Mirrors the patterns in `postgres/codecs-class.ts` and `sqlite/codecs-class.ts` for the single `pg/vector@1` codec. Three artifacts:
*
* 1. `PgVectorCodec` extends {@link CodecImpl} with the runtime encode/decode/encodeJson/decodeJson conversions inline. Conversions are simple enough (PostgreSQL `[1,2,3]` text format) that no shared helper module is warranted; the class body is the source of truth.
* 2. `PgVectorDescriptor` extends {@link CodecDescriptorImpl} with the codec id, traits, target types, params schema (`{ length: number }`, validated against {@link VECTOR_MAX_DIM}), `meta` (postgres `nativeType: 'vector'`), and the emit-path `renderOutputType` producing `Vector<${length}>`.
* 2. `PgVectorDescriptor` extends {@link PostgresCodecDescriptor} with the codec id, traits, target types, params schema (`{ length: number }`, validated against {@link VECTOR_MAX_DIM}), `meta` (postgres `nativeType: 'vector'`), explicit target behavior, and the emit-path `renderOutputType` producing `Vector<${length}>`.
* 3. `pgVectorColumn(length)` per-codec column helper invoking `descriptor.factory({ length })` directly + passing the bare `nativeType: 'vector'`. The family-layer {@link expandNativeType} hook renders the parameterized form (`vector(1536)`) at emit/verify time from `nativeType` + `typeParams`.
*
* `length` threads into the runtime codec via the constructor so encode/decode/encodeJson/decodeJson enforce the declared dimension at every ingress path. Without this, `vector(3)` and `vector(1536)` would produce codecs with identical behaviour and a dimension-mismatched value would round-trip undetected.
Expand All @@ -14,14 +14,17 @@ import type { JsonValue } from '@prisma-next/contract/types';
import {
type AnyCodecDescriptor,
type CodecCallContext,
CodecDescriptorImpl,
CodecImpl,
type CodecInstanceContext,
type ColumnHelperFor,
type ColumnHelperForStrict,
column,
} from '@prisma-next/framework-components/codec';
import type { ExtractCodecTypes } from '@prisma-next/sql-relational-core/ast';
import type { ExtractCodecTypes, ProjectionExpr } from '@prisma-next/sql-relational-core/ast';
import {
definePostgresCodecs,
PostgresCodecDescriptor,
} from '@prisma-next/target-postgres/codec-descriptor';
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { type as arktype } from 'arktype';
import { VECTOR_CODEC_ID, VECTOR_MAX_DIM } from './constants';
Expand Down Expand Up @@ -147,7 +150,13 @@ export class PgVectorCodec extends CodecImpl<
}
}

export class PgVectorDescriptor extends CodecDescriptorImpl<VectorParams> {
export class PgVectorDescriptor extends PostgresCodecDescriptor<VectorParams> {
protected override nativeType(): string {
return PG_VECTOR_META.db.sql.postgres.nativeType;
}
protected override jsonProjection(expression: ProjectionExpr): ProjectionExpr {
return expression;
}
override readonly codecId = VECTOR_CODEC_ID;
override readonly traits = ['equality'] as const;
override readonly targetTypes = ['vector'] as const;
Expand Down Expand Up @@ -180,4 +189,4 @@ const codecDescriptorMap = {

export type CodecTypes = ExtractCodecTypes<typeof codecDescriptorMap>;

export const codecDescriptors: readonly AnyCodecDescriptor[] = Object.values(codecDescriptorMap);
export const codecDescriptors = definePostgresCodecs(Object.values(codecDescriptorMap));
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import pgvector from '@prisma-next/extension-pgvector/pack';
import { defineContract } from '@prisma-next/postgres/contract-builder';

export const pgvectorContract = defineContract({ extensions: { pgvector } }, ({ type }) => ({
types: {
Vector3: type.pgvector.Vector(3),
},
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { ExtractCodecTypes } from '@prisma-next/sql-contract/types';
import { expectTypeOf, test } from 'vitest';
import { pgvectorContract } from './contract-declaration-portability.fixture';

type ContractCodecTypes = ExtractCodecTypes<typeof pgvectorContract>;
type PgvectorCodecTypes = NonNullable<
(typeof pgvectorContract.extensions.pgvector)['__codecTypes']
>;

test('exported contracts retain pgvector public type metadata', () => {
const extension = pgvectorContract.extensions.pgvector;

expectTypeOf(pgvectorContract.target).toEqualTypeOf<'postgres'>();
expectTypeOf(pgvectorContract.targetFamily).toEqualTypeOf<'sql'>();
expectTypeOf(extension.kind).toEqualTypeOf<'extension'>();
expectTypeOf(extension.id).toEqualTypeOf<'pgvector'>();
expectTypeOf(extension.familyId).toEqualTypeOf<'sql'>();
expectTypeOf(extension.targetId).toEqualTypeOf<'postgres'>();
expectTypeOf(extension.capabilities.postgres['pgvector.cosine']).toEqualTypeOf<true>();
expectTypeOf(extension.authoring.type.pgvector.Vector.kind).toEqualTypeOf<'typeConstructor'>();
expectTypeOf(
extension.types.codecTypes.import.package,
).toEqualTypeOf<'@prisma-next/extension-pgvector/codec-types'>();
expectTypeOf<PgvectorCodecTypes['pg/vector@1']['input']>().toEqualTypeOf<number[]>();
expectTypeOf<PgvectorCodecTypes['pg/vector@1']['output']>().toEqualTypeOf<number[]>();
expectTypeOf<ContractCodecTypes['pg/vector@1']['input']>().toEqualTypeOf<number[]>();
expectTypeOf<ContractCodecTypes['pg/vector@1']['output']>().toEqualTypeOf<number[]>();
expectTypeOf<ContractCodecTypes['pg/vector@1']['traits']>().toEqualTypeOf<'equality'>();
});
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ describe('PostgresControlAdapter.lower / PostgresAdapterImpl.lower parity', () =
.withWhere(
BinaryExpr.eq(
ColumnRef.of('user', 'vector'),
ParamRef.of([1, 2, 3], { name: 'vec', codec: { codecId: 'pg/vector@1' } }),
ParamRef.of([1, 2, 3], {
name: 'vec',
codec: { codecId: 'pg/vector@1', typeParams: { length: 3 } },
}),
),
);
expectParity(vectorAst);
Expand Down
12 changes: 10 additions & 2 deletions packages/3-extensions/pgvector/test/operation-lowering.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ describe('Operation lowering', () => {
return new OperationExpr({
method: 'cosineDistance',
self: ColumnRef.of('user', 'vector'),
args: [ParamRef.of([1, 2, 3], { name: 'other', codec: { codecId: 'pg/vector@1' } })],
args: [
ParamRef.of([1, 2, 3], {
name: 'other',
codec: { codecId: 'pg/vector@1', typeParams: { length: 3 } },
}),
],
returns: { codecId: 'core/float8', nullable: false },
lowering: {
targetFamily: 'sql',
Expand All @@ -88,7 +93,10 @@ describe('Operation lowering', () => {
self: ColumnRef.of('user', 'vector'),
args: [
ColumnRef.of('user', 'otherVector'),
ParamRef.of([1, 2, 3], { name: 'param', codec: { codecId: 'pg/vector@1' } }),
ParamRef.of([1, 2, 3], {
name: 'param',
codec: { codecId: 'pg/vector@1', typeParams: { length: 3 } },
}),
LiteralExpr.of(42),
],
returns: { codecId: 'core/float8', nullable: false },
Expand Down
2 changes: 1 addition & 1 deletion packages/3-extensions/pgvector/test/operations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('pgvector operations', () => {
expect(operations).toBeDefined();
expect(Object.keys(operations).sort()).toEqual(['cosineDistance', 'cosineSimilarity']);

const vectorCodec: CodecRef = { codecId: 'pg/vector@1' };
const vectorCodec: CodecRef = { codecId: 'pg/vector@1', typeParams: { length: 2 } };
const cosineDistanceOp = operations['cosineDistance'];
expect(cosineDistanceOp).toBeDefined();
const distExpr = cosineDistanceOp?.impl(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { CodecInstanceContext } from '@prisma-next/framework-components/codec';
import type { AnyPostgresCodecDescriptor } from '@prisma-next/target-postgres/codec-descriptor';
import { expectTypeOf, test } from 'vitest';
import {
codecDescriptors,
type PgVectorCodec,
type PgVectorDescriptor,
pgVectorColumn,
pgVectorDescriptor,
} from '../src/core/codecs';
import type { CodecTypes } from '../src/exports/codec-types';

test('pgvector canonical descriptors are PostgreSQL target descriptors', () => {
expectTypeOf(codecDescriptors).toExtend<readonly AnyPostgresCodecDescriptor[]>();
expectTypeOf<(typeof codecDescriptors)[number]>().toEqualTypeOf<PgVectorDescriptor>();
});

test('pgvector factory and column dimension types remain exact', () => {
expectTypeOf(pgVectorDescriptor.factory({ length: 3 })).toEqualTypeOf<
(ctx: CodecInstanceContext) => PgVectorCodec
>();
expectTypeOf(pgVectorColumn(3).typeParams).toExtend<{ readonly length: 3 }>();
expectTypeOf<CodecTypes['pg/vector@1']['input']>().toEqualTypeOf<number[]>();
expectTypeOf<CodecTypes['pg/vector@1']['output']>().toEqualTypeOf<number[]>();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ColumnRef } from '@prisma-next/sql-relational-core/ast';
import { describe, expect, it } from 'vitest';
import { codecDescriptors, pgVectorDescriptor } from '../src/core/codecs';
import { pgvectorCodecRegistry } from '../src/core/registry';
import pgvectorExtensionDescriptor from '../src/exports/control';
import pgvectorRuntimeDescriptor from '../src/exports/runtime';

describe('pgvector PostgreSQL codec descriptor adoption', () => {
it('uses one target descriptor instance across canonical, registry, runtime, and control contributions', () => {
expect(codecDescriptors).toEqual([pgVectorDescriptor]);
expect(
codecDescriptors.every((descriptor) => descriptor.descriptorKind === 'postgres-codec'),
).toBe(true);
expect([...pgvectorCodecRegistry.values()]).toEqual(codecDescriptors);
expect(pgvectorRuntimeDescriptor.codecs()).toEqual(codecDescriptors);
expect(pgvectorRuntimeDescriptor.types?.codecTypes?.codecDescriptors).toEqual(codecDescriptors);
expect(pgvectorExtensionDescriptor.types?.codecTypes?.codecDescriptors).toEqual(
codecDescriptors,
);
});

it('preserves vector native type, identity projection, and PostgreSQL JSON text', () => {
const ref = { codecId: pgVectorDescriptor.codecId, typeParams: { length: 3 } };
const expression = ColumnRef.of('records', 'embedding');

expect(pgVectorDescriptor.nativeTypeFor(ref)).toBe('vector');
expect(pgVectorDescriptor.meta?.db?.sql?.postgres?.nativeType).toBe('vector');
expect(pgVectorDescriptor.projectJson(expression, ref)).toBe(expression);

const codec = pgVectorDescriptor.factory(ref.typeParams)({ name: 'embedding' });
expect(codec.encodeJson([0.1, 0.2, 0.3])).toBe('[0.1,0.2,0.3]');
expect(codec.decodeJson('[0.1,0.2,0.3]')).toEqual([0.1, 0.2, 0.3]);
});
});
7 changes: 6 additions & 1 deletion packages/3-extensions/pgvector/test/rich-adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,12 @@ describe('Postgres rich AST lowering', () => {
const distance = new OperationExpr({
method: 'cosineDistance',
self: ColumnRef.of('user', 'vector'),
args: [ParamRef.of([1, 2, 3], { name: 'other', codec: { codecId: 'pg/vector@1' } })],
args: [
ParamRef.of([1, 2, 3], {
name: 'other',
codec: { codecId: 'pg/vector@1', typeParams: { length: 3 } },
}),
],
returns: { codecId: 'core/float8', nullable: false },
lowering: {
targetFamily: 'sql',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ describe('pgvector cast policy', () => {
.withWhere(
BinaryExpr.eq(
ColumnRef.of('user', 'vec'),
ParamRef.of([1, 2, 3], { name: 'vec', codec: { codecId: 'pg/vector@1' } }),
ParamRef.of([1, 2, 3], {
name: 'vec',
codec: { codecId: 'pg/vector@1', typeParams: { length: 3 } },
}),
),
);
const lowered = adapter.lower(ast, { contract: vectorContract });
Expand Down
Loading
Loading