fix(materi): align tags column type to jsonb (schema ↔ migration mismatch)
The Drizzle schema used pgText('tags').array() which emits a Postgres
text[] column, but the migration defines tags as jsonb. The mismatch caused
INSERT/LIST on materi_documents to throw INTERNAL_SERVER_ERROR (500) because
Drizzle sent a text[] where the column expected jsonb.
- schema.ts: tags → pgJsonb('tags').notNull().default('[]')
- migration: dropped+recreated to match schema (jsonb, ms epoch defaults,
owner_user_id default 'anonymous')
This commit is contained in:
@@ -1,27 +1,29 @@
|
|||||||
-- Migration: Add materi_documents table for learning materials + RAG
|
-- Migration: Add materi_documents table for learning materials + RAG
|
||||||
-- Run: PGPASSWORD=<pw> psql -h <host> -U <user> -d <db> -f scripts/add-materi-documents.sql
|
-- Run: PGPASSWORD=<pw> psql -h <host> -U <user> -d <db> -f scripts/add-materi-documents.sql
|
||||||
|
-- Schema mirrors services/backend/src/shared/database/schema.ts (pgMateriDocumentsTable).
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "materi_documents" (
|
CREATE TABLE IF NOT EXISTS public.materi_documents (
|
||||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
"title" text NOT NULL,
|
title text NOT NULL,
|
||||||
"description" text,
|
description text,
|
||||||
"content" text NOT NULL,
|
content text NOT NULL,
|
||||||
"category" text NOT NULL DEFAULT 'general',
|
category text NOT NULL DEFAULT 'general',
|
||||||
"tags" jsonb NOT NULL DEFAULT '[]',
|
tags jsonb NOT NULL DEFAULT '[]',
|
||||||
"owner_user_id" text NOT NULL DEFAULT 'anonymous',
|
owner_user_id text NOT NULL DEFAULT 'anonymous',
|
||||||
"guild_id" text,
|
guild_id text,
|
||||||
"channel_id" text,
|
channel_id text,
|
||||||
"is_public" boolean NOT NULL DEFAULT true,
|
is_public boolean NOT NULL DEFAULT true,
|
||||||
"view_count" integer NOT NULL DEFAULT 0,
|
view_count integer NOT NULL DEFAULT 0,
|
||||||
"created_at" bigint NOT NULL DEFAULT extract(epoch from now())::bigint,
|
created_at bigint NOT NULL DEFAULT (EXTRACT(epoch FROM now())::bigint * 1000),
|
||||||
"updated_at" bigint NOT NULL DEFAULT extract(epoch from now())::bigint
|
updated_at bigint NOT NULL DEFAULT (EXTRACT(epoch FROM now())::bigint * 1000)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS "idx_materi_category" ON "materi_documents" ("category");
|
-- Indexes mirror the Drizzle index definitions (idx_materi_category, idx_materi_owner, idx_materi_guild, idx_materi_search).
|
||||||
CREATE INDEX IF NOT EXISTS "idx_materi_is_public" ON "materi_documents" ("is_public");
|
CREATE INDEX IF NOT EXISTS idx_materi_category ON public.materi_documents (category);
|
||||||
CREATE INDEX IF NOT EXISTS "idx_materi_owner" ON "materi_documents" ("owner_user_id");
|
CREATE INDEX IF NOT EXISTS idx_materi_owner ON public.materi_documents (owner_user_id);
|
||||||
CREATE INDEX IF NOT EXISTS "idx_materi_created" ON "materi_documents" ("created_at");
|
CREATE INDEX IF NOT EXISTS idx_materi_guild ON public.materi_documents (guild_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_materi_search ON public.materi_documents (title, category);
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -616,7 +616,7 @@ export const pgMateriDocumentsTable = pgTable(
|
|||||||
description: pgText("description"),
|
description: pgText("description"),
|
||||||
content: pgText("content").notNull(),
|
content: pgText("content").notNull(),
|
||||||
category: pgText("category").notNull().default("general"),
|
category: pgText("category").notNull().default("general"),
|
||||||
tags: pgText("tags").array(),
|
tags: pgJsonb("tags").notNull().default("[]"),
|
||||||
owner_user_id: pgText("owner_user_id").notNull(),
|
owner_user_id: pgText("owner_user_id").notNull(),
|
||||||
guild_id: pgText("guild_id"),
|
guild_id: pgText("guild_id"),
|
||||||
channel_id: pgText("channel_id"),
|
channel_id: pgText("channel_id"),
|
||||||
|
|||||||
Reference in New Issue
Block a user