webupdate
This commit is contained in:
271
backend/fix-database-issues.sql
Normal file
271
backend/fix-database-issues.sql
Normal file
@@ -0,0 +1,271 @@
|
||||
-- Database Schema Fixes and Optimizations
|
||||
-- Generated: 2026-01-16
|
||||
|
||||
-- ==========================================
|
||||
-- 1. ADD MISSING COLUMNS
|
||||
-- ==========================================
|
||||
|
||||
-- Add missing timestamps to products if not exists
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'products' AND column_name = 'deleted_at'
|
||||
) THEN
|
||||
ALTER TABLE products ADD COLUMN deleted_at TIMESTAMP;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Add missing order columns
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'orders' AND column_name = 'customer_id'
|
||||
) THEN
|
||||
ALTER TABLE orders ADD COLUMN customer_id UUID;
|
||||
ALTER TABLE orders ADD CONSTRAINT fk_orders_customer
|
||||
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE SET NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = 'orders' AND column_name = 'shipping_address'
|
||||
) THEN
|
||||
ALTER TABLE orders ADD COLUMN shipping_address JSONB;
|
||||
ALTER TABLE orders ADD COLUMN billing_address JSONB;
|
||||
ALTER TABLE orders ADD COLUMN payment_method VARCHAR(50);
|
||||
ALTER TABLE orders ADD COLUMN tracking_number VARCHAR(100);
|
||||
ALTER TABLE orders ADD COLUMN notes TEXT;
|
||||
ALTER TABLE orders ADD COLUMN created_at TIMESTAMP DEFAULT NOW();
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- ==========================================
|
||||
-- 2. FIX DATA TYPE INCONSISTENCIES
|
||||
-- ==========================================
|
||||
|
||||
-- Ensure consistent boolean defaults
|
||||
ALTER TABLE products ALTER COLUMN isfeatured SET DEFAULT false;
|
||||
ALTER TABLE products ALTER COLUMN isbestseller SET DEFAULT false;
|
||||
ALTER TABLE products ALTER COLUMN isactive SET DEFAULT true;
|
||||
|
||||
ALTER TABLE product_images ALTER COLUMN is_primary SET DEFAULT false;
|
||||
ALTER TABLE product_images ALTER COLUMN display_order SET DEFAULT 0;
|
||||
ALTER TABLE product_images ALTER COLUMN variant_stock SET DEFAULT 0;
|
||||
|
||||
ALTER TABLE blogposts ALTER COLUMN ispublished SET DEFAULT false;
|
||||
ALTER TABLE blogposts ALTER COLUMN isactive SET DEFAULT true;
|
||||
|
||||
ALTER TABLE pages ALTER COLUMN ispublished SET DEFAULT true;
|
||||
ALTER TABLE pages ALTER COLUMN isactive SET DEFAULT true;
|
||||
|
||||
ALTER TABLE portfolioprojects ALTER COLUMN isactive SET DEFAULT true;
|
||||
|
||||
-- ==========================================
|
||||
-- 3. ADD MISSING INDEXES FOR PERFORMANCE
|
||||
-- ==========================================
|
||||
|
||||
-- Products: Add indexes for common queries
|
||||
CREATE INDEX IF NOT EXISTS idx_products_active_bestseller
|
||||
ON products(isactive, isbestseller) WHERE isactive = true AND isbestseller = true;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_products_category_active
|
||||
ON products(category, isactive) WHERE isactive = true;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_products_price_range
|
||||
ON products(price) WHERE isactive = true;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_products_stock
|
||||
ON products(stockquantity) WHERE isactive = true;
|
||||
|
||||
-- Product Images: Optimize joins
|
||||
CREATE INDEX IF NOT EXISTS idx_product_images_product_order
|
||||
ON product_images(product_id, display_order);
|
||||
|
||||
-- Blog: Add missing indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_blogposts_published_date
|
||||
ON blogposts(publisheddate DESC) WHERE ispublished = true;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_blogposts_category
|
||||
ON blogposts(category) WHERE ispublished = true;
|
||||
|
||||
-- Pages: Add index for active lookup
|
||||
CREATE INDEX IF NOT EXISTS idx_pages_slug_active
|
||||
ON pages(slug) WHERE isactive = true AND ispublished = true;
|
||||
|
||||
-- Orders: Add indexes for queries
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_customer
|
||||
ON orders(customer_id) WHERE customer_id IS NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_status
|
||||
ON orders(orderstatus);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_date
|
||||
ON orders(orderdate DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_number
|
||||
ON orders(ordernumber);
|
||||
|
||||
-- Customers: Add indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_customers_email_active
|
||||
ON customers(email) WHERE is_active = true;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_customers_created
|
||||
ON customers(created_at DESC);
|
||||
|
||||
-- ==========================================
|
||||
-- 4. ADD MISSING CONSTRAINTS
|
||||
-- ==========================================
|
||||
|
||||
-- Ensure products have valid prices
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'chk_products_price_positive'
|
||||
) THEN
|
||||
ALTER TABLE products ADD CONSTRAINT chk_products_price_positive
|
||||
CHECK (price >= 0);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'chk_products_stock_nonnegative'
|
||||
) THEN
|
||||
ALTER TABLE products ADD CONSTRAINT chk_products_stock_nonnegative
|
||||
CHECK (stockquantity >= 0);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Ensure product images have valid ordering
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'chk_product_images_order_nonnegative'
|
||||
) THEN
|
||||
ALTER TABLE product_images ADD CONSTRAINT chk_product_images_order_nonnegative
|
||||
CHECK (display_order >= 0);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE constraint_name = 'chk_product_images_stock_nonnegative'
|
||||
) THEN
|
||||
ALTER TABLE product_images ADD CONSTRAINT chk_product_images_stock_nonnegative
|
||||
CHECK (variant_stock >= 0);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Ensure orders have valid amounts
|
||||
ALTER TABLE orders DROP CONSTRAINT IF EXISTS chk_orders_amounts;
|
||||
ALTER TABLE orders ADD CONSTRAINT chk_orders_amounts
|
||||
CHECK (subtotal >= 0 AND total >= 0);
|
||||
|
||||
-- ==========================================
|
||||
-- 5. ADD CASCADE DELETE FOR ORPHANED DATA
|
||||
-- ==========================================
|
||||
|
||||
-- Ensure product images are deleted when product is deleted
|
||||
ALTER TABLE product_images DROP CONSTRAINT IF EXISTS product_images_product_id_fkey;
|
||||
ALTER TABLE product_images ADD CONSTRAINT product_images_product_id_fkey
|
||||
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE;
|
||||
|
||||
-- ==========================================
|
||||
-- 6. CREATE MISSING TABLES
|
||||
-- ==========================================
|
||||
|
||||
-- Create order_items if missing
|
||||
CREATE TABLE IF NOT EXISTS order_items (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::TEXT,
|
||||
order_id TEXT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
||||
product_id TEXT REFERENCES products(id) ON DELETE SET NULL,
|
||||
product_name VARCHAR(255) NOT NULL,
|
||||
product_sku VARCHAR(100),
|
||||
quantity INTEGER NOT NULL CHECK (quantity > 0),
|
||||
unit_price NUMERIC(10,2) NOT NULL CHECK (unit_price >= 0),
|
||||
total_price NUMERIC(10,2) NOT NULL CHECK (total_price >= 0),
|
||||
color_variant VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_order_items_order ON order_items(order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_order_items_product ON order_items(product_id);
|
||||
|
||||
-- Create reviews table if missing
|
||||
CREATE TABLE IF NOT EXISTS product_reviews (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::TEXT,
|
||||
product_id TEXT NOT NULL REFERENCES products(id) ON DELETE CASCADE,
|
||||
customer_id UUID REFERENCES customers(id) ON DELETE CASCADE,
|
||||
rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
|
||||
title VARCHAR(200),
|
||||
comment TEXT,
|
||||
is_verified_purchase BOOLEAN DEFAULT false,
|
||||
is_approved BOOLEAN DEFAULT false,
|
||||
helpful_count INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_reviews_product ON product_reviews(product_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reviews_customer ON product_reviews(customer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reviews_approved ON product_reviews(is_approved) WHERE is_approved = true;
|
||||
|
||||
-- ==========================================
|
||||
-- 7. ADD TRIGGERS FOR AUTOMATIC TIMESTAMPS
|
||||
-- ==========================================
|
||||
|
||||
-- Function to update updated_at timestamp
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updatedat = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
-- Add triggers for products
|
||||
DROP TRIGGER IF EXISTS update_products_updatedat ON products;
|
||||
CREATE TRIGGER update_products_updatedat
|
||||
BEFORE UPDATE ON products
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Add triggers for blogposts
|
||||
DROP TRIGGER IF EXISTS update_blogposts_updatedat ON blogposts;
|
||||
CREATE TRIGGER update_blogposts_updatedat
|
||||
BEFORE UPDATE ON blogposts
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Add triggers for pages
|
||||
DROP TRIGGER IF EXISTS update_pages_updatedat ON pages;
|
||||
CREATE TRIGGER update_pages_updatedat
|
||||
BEFORE UPDATE ON pages
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- ==========================================
|
||||
-- 8. UPDATE STATISTICS FOR QUERY PLANNER
|
||||
-- ==========================================
|
||||
|
||||
ANALYZE products;
|
||||
ANALYZE product_images;
|
||||
ANALYZE blogposts;
|
||||
ANALYZE pages;
|
||||
ANALYZE portfolioprojects;
|
||||
ANALYZE orders;
|
||||
ANALYZE customers;
|
||||
|
||||
-- ==========================================
|
||||
-- COMPLETE
|
||||
-- ==========================================
|
||||
|
||||
SELECT 'Database schema fixes applied successfully!' AS status;
|
||||
Reference in New Issue
Block a user