From 53a244013987bfd54b9f12f5879d3dd6b991d0fc Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 19 Jun 2026 22:55:25 +0100 Subject: [PATCH] feat(base): make property id varchar with per-base composite pk --- .../migrations/20260529T125146-bases.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/server/src/database/migrations/20260529T125146-bases.ts b/apps/server/src/database/migrations/20260529T125146-bases.ts index 8d7341fb8..c32b6954d 100644 --- a/apps/server/src/database/migrations/20260529T125146-bases.ts +++ b/apps/server/src/database/migrations/20260529T125146-bases.ts @@ -20,9 +20,7 @@ export async function up(db: Kysely): Promise { await db.schema .createTable('base_properties') .ifNotExists() - .addColumn('id', 'uuid', (col) => - col.primaryKey().defaultTo(sql`gen_uuid_v7()`), - ) + .addColumn('id', 'varchar', (col) => col.notNull()) .addColumn('page_id', 'uuid', (col) => col.references('pages.id').onDelete('cascade').notNull(), ) @@ -45,6 +43,7 @@ export async function up(db: Kysely): Promise { col.notNull().defaultTo(sql`now()`), ) .addColumn('deleted_at', 'timestamptz') + .addPrimaryKeyConstraint('base_properties_pkey', ['page_id', 'id']) .execute(); await sql`CREATE INDEX IF NOT EXISTS idx_base_properties_page_id ON base_properties (page_id)`.execute( @@ -151,13 +150,13 @@ export async function up(db: Kysely): Promise { // Cell extraction helpers for filters and sorts. Return NULL for absent or // non-castable values. await sql` - CREATE OR REPLACE FUNCTION base_cell_text(cells jsonb, prop uuid) + CREATE OR REPLACE FUNCTION base_cell_text(cells jsonb, prop text) RETURNS text LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT cells->>prop::text $$ `.execute(db); await sql` - CREATE OR REPLACE FUNCTION base_cell_numeric(cells jsonb, prop uuid) + CREATE OR REPLACE FUNCTION base_cell_numeric(cells jsonb, prop text) RETURNS numeric LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT CASE jsonb_typeof(cells->prop::text) @@ -176,7 +175,7 @@ export async function up(db: Kysely): Promise { // cast can fail on values no regex can pre-validate (e.g. '2024-13-45'). This // helper uses plpgsql with an EXCEPTION handler to return NULL on failure. await sql` - CREATE OR REPLACE FUNCTION base_cell_timestamptz(cells jsonb, prop uuid) + CREATE OR REPLACE FUNCTION base_cell_timestamptz(cells jsonb, prop text) RETURNS timestamptz LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE AS $$ BEGIN RETURN (cells->>prop::text)::timestamptz; @@ -185,7 +184,7 @@ export async function up(db: Kysely): Promise { `.execute(db); await sql` - CREATE OR REPLACE FUNCTION base_cell_bool(cells jsonb, prop uuid) + CREATE OR REPLACE FUNCTION base_cell_bool(cells jsonb, prop text) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT CASE jsonb_typeof(cells->prop::text) @@ -201,7 +200,7 @@ export async function up(db: Kysely): Promise { `.execute(db); await sql` - CREATE OR REPLACE FUNCTION base_cell_array(cells jsonb, prop uuid) + CREATE OR REPLACE FUNCTION base_cell_array(cells jsonb, prop text) RETURNS jsonb LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT cells->prop::text $$ `.execute(db); @@ -236,11 +235,11 @@ export async function down(db: Kysely): Promise { await db.schema.dropTable('base_properties').execute(); await sql`DROP FUNCTION jsonb_set_many(jsonb, jsonb)`.execute(db); - await sql`DROP FUNCTION base_cell_array(jsonb, uuid)`.execute(db); - await sql`DROP FUNCTION base_cell_bool(jsonb, uuid)`.execute(db); - await sql`DROP FUNCTION base_cell_timestamptz(jsonb, uuid)`.execute(db); - await sql`DROP FUNCTION base_cell_numeric(jsonb, uuid)`.execute(db); - await sql`DROP FUNCTION base_cell_text(jsonb, uuid)`.execute(db); + await sql`DROP FUNCTION base_cell_array(jsonb, text)`.execute(db); + await sql`DROP FUNCTION base_cell_bool(jsonb, text)`.execute(db); + await sql`DROP FUNCTION base_cell_timestamptz(jsonb, text)`.execute(db); + await sql`DROP FUNCTION base_cell_numeric(jsonb, text)`.execute(db); + await sql`DROP FUNCTION base_cell_text(jsonb, text)`.execute(db); await sql`DROP INDEX idx_pages_is_base`.execute(db); await db.schema