You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senzapaura_es/drizzle/0007_compras_con_clave_fora...

126 lines
8.4 KiB

Las compras dejan de apuntar a un texto y apuntan a la canción Fase 3 del modelo, que iba primero por ser lo único que podía costarle dinero a alguien: siete tablas guardaban `cancion_slug` sin clave foránea, porque cuando se escribieron el catálogo vivía en archivos y no había a qué apuntar. Renombrar un slug dejaba huérfana una compra en silencio, y quien la había pagado se enteraba al intentar descargar. Ahora apuntan a `cancion.id`, que es opaco y no cambia. El borrado no se propaga igual en todas: `compra`, `pedido_item` y `descarga` lo RESTRINGEN —una canción pagada no se puede borrar, y el registro de entrega tiene que sobrevivir a lo que prueba—; `carrito_item`, `favorito`, `valoracion` y `reproduccion` caen con ella. En dos migraciones y no en una: entre la 0007 y la 0008 conviven las dos columnas, así que el despliegue no tiene que parar el sitio. La 0007 se niega a seguir si alguna compra apunta a un slug que ya no existe: borrarla en silencio sería repetir el fallo que esto viene a arreglar. Por fuera nada cambia de forma. Los módulos siguen recibiendo slugs —es lo que hay en las URL— y traducen en el borde, en `$lib/server/canciones`. Al hacerlo, tres funciones pasan a devolver `false` cuando el slug no existe, que antes se guardaba tal cual: se podía meter en el carrito un tema inventado. El script de guardas estaba roto desde que se volcó el catálogo —usaba slugs de verdad y moría en la primera inserción por clave duplicada, sin comprobar nada—. Ahora usa el prefijo `zz-` y el país ZZ, que ISO 3166 reserva para uso privado. Y la prueba de la valoración pasaba por el motivo equivocado: rechazaba el seis porque la columna ya no existía, no por el rango. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
-- Las compras dejan de apuntar a un texto y apuntan a la canción.
--
-- Siete tablas guardaban `cancion_slug` sin clave foránea, porque cuando se
-- escribieron el catálogo vivía en archivos y no había a qué apuntar.
-- Renombrar un slug dejaba huérfana una compra **en silencio**: nadie se
-- enteraba hasta que alguien intentaba descargar lo que había pagado.
--
-- Ahora apuntan a `cancion.id`, que es opaco y no cambia nunca. El slug se
-- queda de momento en su columna, sin obligación, y se borra en la migración
-- siguiente: así el despliegue no necesita parar el sitio —la versión vieja
-- del código sigue leyendo su columna mientras la nueva ya escribe la otra—.
--
-- El borrado no se propaga igual en todas:
--
-- · `compra`, `pedido_item` y `descarga` lo RESTRINGEN. Una canción que
-- alguien ha pagado no se puede borrar de la base, y el registro de
-- entrega tiene que sobrevivir a lo que prueba. Para sacar un tema del
-- catálogo está `estado = 'retirado'`, que es lo que esa columna vino a
-- resolver.
-- · `carrito_item`, `favorito`, `valoracion` y `reproduccion` CAEN con ella:
-- sin la canción no significan nada.
DROP INDEX "reproduccion_cancion";--> statement-breakpoint
DROP INDEX "idx_valoracion_cancion";--> statement-breakpoint
-- Primero la columna vacía; el `NOT NULL` va al final, cuando esté llena.
ALTER TABLE "descarga" ADD COLUMN "cancion_id" text;--> statement-breakpoint
ALTER TABLE "carrito_item" ADD COLUMN "cancion_id" text;--> statement-breakpoint
ALTER TABLE "compra" ADD COLUMN "cancion_id" text;--> statement-breakpoint
ALTER TABLE "pedido_item" ADD COLUMN "cancion_id" text;--> statement-breakpoint
ALTER TABLE "favorito" ADD COLUMN "cancion_id" text;--> statement-breakpoint
ALTER TABLE "reproduccion" ADD COLUMN "cancion_id" text;--> statement-breakpoint
ALTER TABLE "valoracion" ADD COLUMN "cancion_id" text;--> statement-breakpoint
UPDATE "descarga" d SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = d."cancion_slug";--> statement-breakpoint
UPDATE "carrito_item" t SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = t."cancion_slug";--> statement-breakpoint
UPDATE "compra" t SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = t."cancion_slug";--> statement-breakpoint
UPDATE "pedido_item" t SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = t."cancion_slug";--> statement-breakpoint
UPDATE "favorito" t SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = t."cancion_slug";--> statement-breakpoint
UPDATE "reproduccion" t SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = t."cancion_slug";--> statement-breakpoint
UPDATE "valoracion" t SET "cancion_id" = c."id" FROM "cancion" c WHERE c."slug" = t."cancion_slug";--> statement-breakpoint
-- Lo que no se pudo traducir.
--
-- En lo que vale dinero, la migración se para: una compra que apunta a un slug
-- que ya no existe es exactamente el fallo que esto viene a arreglar, y
-- borrarla en silencio sería repetirlo con otra forma. Hay que mirar esas
-- filas a mano y decidir.
DO $$
DECLARE
sueltas integer;
BEGIN
SELECT
(SELECT count(*) FROM "compra" WHERE "cancion_id" IS NULL)
+ (SELECT count(*) FROM "pedido_item" WHERE "cancion_id" IS NULL)
+ (SELECT count(*) FROM "descarga" WHERE "cancion_id" IS NULL)
INTO sueltas;
IF sueltas > 0 THEN
RAISE EXCEPTION
'Hay % filas de compra, pedido_item o descarga cuyo cancion_slug no existe en cancion. Revísalas antes de migrar: son temas pagados que apuntan a la nada.',
sueltas;
END IF;
END $$;--> statement-breakpoint
-- En lo que no vale dinero sí se borran, pero se dice cuántas.
DO $$
DECLARE
quitadas integer := 0;
n integer;
BEGIN
DELETE FROM "carrito_item" WHERE "cancion_id" IS NULL;
GET DIAGNOSTICS n = ROW_COUNT; quitadas := quitadas + n;
DELETE FROM "favorito" WHERE "cancion_id" IS NULL;
GET DIAGNOSTICS n = ROW_COUNT; quitadas := quitadas + n;
DELETE FROM "valoracion" WHERE "cancion_id" IS NULL;
GET DIAGNOSTICS n = ROW_COUNT; quitadas := quitadas + n;
DELETE FROM "reproduccion" WHERE "cancion_id" IS NULL;
GET DIAGNOSTICS n = ROW_COUNT; quitadas := quitadas + n;
IF quitadas > 0 THEN
RAISE NOTICE 'Se han borrado % filas de carrito, favoritos, valoraciones o escuchas que apuntaban a un tema inexistente.', quitadas;
END IF;
END $$;--> statement-breakpoint
ALTER TABLE "descarga" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "carrito_item" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "compra" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "pedido_item" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "favorito" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "reproduccion" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "valoracion" ALTER COLUMN "cancion_id" SET NOT NULL;--> statement-breakpoint
-- La identidad de la fila pasa a ser el par cuenta-canción, no cuenta-texto.
ALTER TABLE "carrito_item" DROP CONSTRAINT "carrito_item_carrito_id_cancion_slug_pk";--> statement-breakpoint
ALTER TABLE "compra" DROP CONSTRAINT "compra_usuario_id_cancion_slug_pk";--> statement-breakpoint
ALTER TABLE "pedido_item" DROP CONSTRAINT "pedido_item_pedido_id_cancion_slug_pk";--> statement-breakpoint
ALTER TABLE "favorito" DROP CONSTRAINT "favorito_usuario_id_cancion_slug_pk";--> statement-breakpoint
ALTER TABLE "valoracion" DROP CONSTRAINT "valoracion_usuario_id_cancion_slug_pk";--> statement-breakpoint
ALTER TABLE "carrito_item" ADD CONSTRAINT "carrito_item_carrito_id_cancion_id_pk" PRIMARY KEY("carrito_id","cancion_id");--> statement-breakpoint
ALTER TABLE "compra" ADD CONSTRAINT "compra_usuario_id_cancion_id_pk" PRIMARY KEY("usuario_id","cancion_id");--> statement-breakpoint
ALTER TABLE "pedido_item" ADD CONSTRAINT "pedido_item_pedido_id_cancion_id_pk" PRIMARY KEY("pedido_id","cancion_id");--> statement-breakpoint
ALTER TABLE "favorito" ADD CONSTRAINT "favorito_usuario_id_cancion_id_pk" PRIMARY KEY("usuario_id","cancion_id");--> statement-breakpoint
ALTER TABLE "valoracion" ADD CONSTRAINT "valoracion_usuario_id_cancion_id_pk" PRIMARY KEY("usuario_id","cancion_id");--> statement-breakpoint
-- La columna vieja se queda un despliegue más, ya sin obligar a nada.
ALTER TABLE "descarga" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "carrito_item" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "compra" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "pedido_item" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "favorito" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "reproduccion" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "valoracion" ALTER COLUMN "cancion_slug" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "descarga" ADD CONSTRAINT "descarga_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "carrito_item" ADD CONSTRAINT "carrito_item_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "compra" ADD CONSTRAINT "compra_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "pedido_item" ADD CONSTRAINT "pedido_item_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "favorito" ADD CONSTRAINT "favorito_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "reproduccion" ADD CONSTRAINT "reproduccion_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "valoracion" ADD CONSTRAINT "valoracion_cancion_id_cancion_id_fk" FOREIGN KEY ("cancion_id") REFERENCES "public"."cancion"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "reproduccion_cancion" ON "reproduccion" USING btree ("cancion_id");--> statement-breakpoint
CREATE INDEX "idx_valoracion_cancion" ON "valoracion" USING btree ("cancion_id");

Powered by TurnKey Linux.