-- 03-migrate-phash-bigint-to-vector.sql -- 兼容旧库:phash 早期以 bigint 存储 64-bit dHash 指纹(uint64),现模型改为 vector(64)。 -- pgvector 不支持 bigint -> vector 直接转换,需逐位拆成 0/1 向量(位 i -> 第 i 维, -- 与 Go 侧 phash.ToVectorBits 完全一致,保证旧数据与新写入向量在同一语义空间可比)。 -- -- 用法(仅升级旧库时需要): -- 本迁移原先由后端启动时的 AutoMigrate(migratePhashSQL)自动执行;AutoMigrate 已移除, -- 故升级老库改回手动执行: -- psql "postgres://fashion:fashion_dev_2026@localhost:5432/fashion" -f 03-migrate-phash-bigint-to-vector.sql -- -- 已为 vector/text 类型的列自动跳过;可重复执行。 DO $$ DECLARE t text; dt text; BEGIN FOR t IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename IN ('brand_runway_images','brand_runway_draft_images','street_snap_images','street_snap_draft_images') LOOP SELECT data_type INTO dt FROM information_schema.columns WHERE table_schema = 'public' AND table_name = t AND column_name = 'phash'; IF dt = 'bigint' THEN -- bigint 即 64-bit dHash 指纹;pgvector 不支持 bigint->vector 直接转换,且 ALTER ... USING 的 -- transform 表达式不允许子查询(0A000)。改用纯表达式:bigint::bit(64) 取 64 位模式(MSB 在左), -- reverse 成 LSB 在左(与 phash.ToVectorBits 维度顺序一致:第 i 维 = bit i),插逗号后 text::vector(64)。 -- NULL 自然透传。 EXECUTE format($e$ ALTER TABLE %I ALTER COLUMN phash TYPE vector(64) USING ( ('[' || rtrim(regexp_replace(reverse(phash::bit(64)::text), '(.)', '\1,', 'g'), ',') || ']')::vector(64) ) $e$, t); RAISE NOTICE 'migrated phash (bigint -> vector) on %', t; ELSIF dt IN ('character varying','text') THEN EXECUTE format($e$ ALTER TABLE %I ALTER COLUMN phash TYPE vector(64) USING phash::vector(64) $e$, t); RAISE NOTICE 'migrated phash (text -> vector) on %', t; ELSE RAISE NOTICE 'phash on % already type %, skipped', t, dt; END IF; END LOOP; END $$;