freshyo/packages/db_helper_sqlite/drizzle/0002_sku_split.sql
2026-08-01 20:18:42 +05:30

249 lines
9.1 KiB
SQL

-- Migration: split product_info into product_info (catalog) + product_skus + sku_features
-- and move all buyable references from product ids to sku ids.
-- PRAGMA foreign_keys=OFF;
PRAGMA defer_foreign_keys = on;
-- 1. Create new SKU tables.
CREATE TABLE `product_skus` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`product_id` integer NOT NULL,
`name` text,
`price` text NOT NULL,
`market_price` text,
`images` text,
`is_out_of_stock` integer DEFAULT false NOT NULL,
`is_suspended` integer DEFAULT false NOT NULL,
`is_flash_available` integer DEFAULT false NOT NULL,
`flash_price` text,
`created_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (`product_id`) REFERENCES `product_info`(`id`) ON UPDATE no action ON DELETE no action
);
CREATE TABLE `sku_features` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`sku_id` integer NOT NULL,
`feature_name` text NOT NULL,
`feature_value` text NOT NULL,
FOREIGN KEY (`sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action
);
CREATE UNIQUE INDEX `unique_sku_feature_name` ON `sku_features` (`sku_id`,`feature_name`);
-- 2. Migrate each existing product into one default SKU plus a mandatory quantity feature.
INSERT INTO `product_skus` (
`product_id`, `name`, `price`, `market_price`, `images`, `is_out_of_stock`,
`is_suspended`, `is_flash_available`, `flash_price`, `created_at`
)
SELECT
`id`,
NULL,
`price`,
`market_price`,
`images`,
`is_out_of_stock`,
`is_suspended`,
`is_flash_available`,
`flash_price`,
`created_at`
FROM `product_info`;
INSERT INTO `sku_features` (`sku_id`, `feature_name`, `feature_value`)
SELECT
`ps`.`id`,
'quantity',
(CAST(`pi`.`product_quantity` AS TEXT)) || COALESCE(`u`.`short_notation`, '')
FROM `product_info` `pi`
JOIN `product_skus` `ps` ON `ps`.`product_id` = `pi`.`id`
LEFT JOIN `units` `u` ON `u`.`id` = `pi`.`unit_id`;
-- 3. Build a product_id -> sku_id mapping for downstream tables.
CREATE TABLE `__product_to_sku` (
`product_id` integer PRIMARY KEY,
`sku_id` integer NOT NULL
);
INSERT INTO `__product_to_sku` (`product_id`, `sku_id`)
SELECT `product_id`, `id` FROM `product_skus`;
-- 4. Recreate product_info with only catalog-level fields.
CREATE TABLE `__new_product_info` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`name` text NOT NULL,
`short_description` text,
`long_description` text,
`store_id` integer,
`increment_step` real DEFAULT 1 NOT NULL,
`created_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (`store_id`) REFERENCES `store_info`(`id`) ON UPDATE no action ON DELETE no action
);
INSERT INTO `__new_product_info` (
`id`, `name`, `short_description`, `long_description`, `store_id`, `increment_step`, `created_at`
)
SELECT
`id`, `name`, `short_description`, `long_description`, `store_id`, `increment_step`, `created_at`
FROM `product_info`;
DROP TABLE `product_info`;
ALTER TABLE `__new_product_info` RENAME TO `product_info`;
-- 5. Recreate tables that previously referenced product_info.id so they now reference product_skus.id.
CREATE TABLE `__new_cart_items` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`user_id` integer NOT NULL,
`sku_id` integer NOT NULL,
`quantity` text NOT NULL,
`added_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action
);
INSERT INTO `__new_cart_items` (`id`, `user_id`, `sku_id`, `quantity`, `added_at`)
SELECT
`ci`.`id`, `ci`.`user_id`, `m`.`sku_id`, `ci`.`quantity`, `ci`.`added_at`
FROM `cart_items` `ci`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `ci`.`product_id`;
DROP TABLE `cart_items`;
ALTER TABLE `__new_cart_items` RENAME TO `cart_items`;
CREATE UNIQUE INDEX `unique_user_sku` ON `cart_items` (`user_id`,`sku_id`);
CREATE TABLE `__new_order_items` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`order_id` integer NOT NULL,
`sku_id` integer NOT NULL,
`quantity` text NOT NULL,
`price` text NOT NULL,
`discounted_price` text,
`is_packaged` integer DEFAULT false NOT NULL,
`is_package_verified` integer DEFAULT false NOT NULL,
FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action
);
INSERT INTO `__new_order_items` (
`id`, `order_id`, `sku_id`, `quantity`, `price`, `discounted_price`, `is_packaged`, `is_package_verified`
)
SELECT
`oi`.`id`, `oi`.`order_id`, `m`.`sku_id`, `oi`.`quantity`, `oi`.`price`,
`oi`.`discounted_price`, `oi`.`is_packaged`, `oi`.`is_package_verified`
FROM `order_items` `oi`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `oi`.`product_id`;
DROP TABLE `order_items`;
ALTER TABLE `__new_order_items` RENAME TO `order_items`;
CREATE TABLE `__new_special_deals` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`sku_id` integer NOT NULL,
`quantity` text NOT NULL,
`price` text NOT NULL,
`valid_till` text NOT NULL,
FOREIGN KEY (`sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action
);
INSERT INTO `__new_special_deals` (`id`, `sku_id`, `quantity`, `price`, `valid_till`)
SELECT
`sd`.`id`, `m`.`sku_id`, `sd`.`quantity`, `sd`.`price`, `sd`.`valid_till`
FROM `special_deals` `sd`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `sd`.`product_id`;
DROP TABLE `special_deals`;
ALTER TABLE `__new_special_deals` RENAME TO `special_deals`;
CREATE TABLE `__new_coupon_applicable_products` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`coupon_id` integer NOT NULL,
`sku_id` integer NOT NULL,
FOREIGN KEY (`coupon_id`) REFERENCES `coupons`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action
);
INSERT INTO `__new_coupon_applicable_products` (`id`, `coupon_id`, `sku_id`)
SELECT
`cap`.`id`, `cap`.`coupon_id`, `m`.`sku_id`
FROM `coupon_applicable_products` `cap`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `cap`.`product_id`;
DROP TABLE `coupon_applicable_products`;
ALTER TABLE `__new_coupon_applicable_products` RENAME TO `coupon_applicable_products`;
CREATE UNIQUE INDEX `unique_coupon_sku` ON `coupon_applicable_products` (`coupon_id`,`sku_id`);
-- 6. Remap JSON product id arrays to sku id arrays (before renaming the columns).
UPDATE `delivery_slot_info` AS `target`
SET `product_ids` = COALESCE(
(SELECT json_group_array(`m`.`sku_id`)
FROM json_each(`target`.`product_ids`) AS `je`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `je`.`value`),
CASE WHEN `target`.`product_ids` IS NULL THEN NULL ELSE '[]' END
);
UPDATE `home_banners` AS `target`
SET `product_ids` = COALESCE(
(SELECT json_group_array(`m`.`sku_id`)
FROM json_each(`target`.`product_ids`) AS `je`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `je`.`value`),
CASE WHEN `target`.`product_ids` IS NULL THEN NULL ELSE '[]' END
);
UPDATE `coupons` AS `target`
SET `product_ids` = COALESCE(
(SELECT json_group_array(`m`.`sku_id`)
FROM json_each(`target`.`product_ids`) AS `je`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `je`.`value`),
CASE WHEN `target`.`product_ids` IS NULL THEN NULL ELSE '[]' END
);
UPDATE `reserved_coupons` AS `target`
SET `product_ids` = COALESCE(
(SELECT json_group_array(`m`.`sku_id`)
FROM json_each(`target`.`product_ids`) AS `je`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `je`.`value`),
CASE WHEN `target`.`product_ids` IS NULL THEN NULL ELSE '[]' END
);
UPDATE `vendor_snippets` AS `target`
SET `product_ids` = COALESCE(
(SELECT json_group_array(`m`.`sku_id`)
FROM json_each(`target`.`product_ids`) AS `je`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `je`.`value`),
'[]'
);
-- 7. Rename JSON columns from product_ids to sku_ids.
ALTER TABLE `delivery_slot_info` RENAME COLUMN `product_ids` TO `sku_ids`;
ALTER TABLE `home_banners` RENAME COLUMN `product_ids` TO `sku_ids`;
ALTER TABLE `coupons` RENAME COLUMN `product_ids` TO `sku_ids`;
ALTER TABLE `reserved_coupons` RENAME COLUMN `product_ids` TO `sku_ids`;
ALTER TABLE `vendor_snippets` RENAME COLUMN `product_ids` TO `sku_ids`;
-- 8. Update popularItems in key_val_store from product IDs to SKU IDs.
UPDATE `key_val_store`
SET `value` = (
SELECT json_group_array(`m`.`sku_id`)
FROM json_each(`key_val_store`.`value`) AS `je`
JOIN `__product_to_sku` `m` ON `m`.`product_id` = `je`.`value`
)
WHERE `key` = 'popularItems'
AND `value` IS NOT NULL
AND `value` LIKE '[%';
-- 9. Clean up helper table.
DROP TABLE `__product_to_sku`;
-- 10. Add product_type column and product_combos table for combo products.
ALTER TABLE `product_info` ADD COLUMN `product_type` text DEFAULT 'item';
CREATE TABLE `product_combos` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`combo_sku_id` integer NOT NULL,
`sku_id` integer NOT NULL,
FOREIGN KEY (`combo_sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`sku_id`) REFERENCES `product_skus`(`id`) ON UPDATE no action ON DELETE no action
);
CREATE UNIQUE INDEX `unique_combo_sku_item` ON `product_combos` (`combo_sku_id`,`sku_id`);
-- PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys = off;