- Schema creation and grants - Enums: product_type, product_status, price_type, attribute_type - Tables: categories, products, variants, prices - RLS policies for tenant isolation - Performance indexes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
120 lines
5.2 KiB
SQL
120 lines
5.2 KiB
SQL
-- ============================================
|
|
-- TEMPLATE-SAAS: Portfolio Indexes
|
|
-- Version: 1.0.0
|
|
-- Module: SAAS-019
|
|
-- ============================================
|
|
|
|
-- ============================================
|
|
-- Categories Indexes
|
|
-- ============================================
|
|
CREATE INDEX idx_categories_tenant ON portfolio.categories(tenant_id);
|
|
CREATE INDEX idx_categories_parent ON portfolio.categories(tenant_id, parent_id);
|
|
CREATE INDEX idx_categories_slug ON portfolio.categories(tenant_id, slug);
|
|
CREATE INDEX idx_categories_position ON portfolio.categories(tenant_id, parent_id, position);
|
|
CREATE INDEX idx_categories_active ON portfolio.categories(tenant_id, is_active) WHERE is_active = TRUE;
|
|
|
|
-- Soft delete filter
|
|
CREATE INDEX idx_categories_not_deleted ON portfolio.categories(tenant_id)
|
|
WHERE deleted_at IS NULL;
|
|
|
|
-- ============================================
|
|
-- Products Indexes
|
|
-- ============================================
|
|
-- Primary indexes
|
|
CREATE INDEX idx_products_tenant ON portfolio.products(tenant_id);
|
|
CREATE INDEX idx_products_category ON portfolio.products(tenant_id, category_id) WHERE category_id IS NOT NULL;
|
|
CREATE INDEX idx_products_slug ON portfolio.products(tenant_id, slug);
|
|
CREATE INDEX idx_products_sku ON portfolio.products(tenant_id, sku) WHERE sku IS NOT NULL;
|
|
CREATE INDEX idx_products_status ON portfolio.products(tenant_id, status);
|
|
CREATE INDEX idx_products_type ON portfolio.products(tenant_id, product_type);
|
|
|
|
-- Search indexes
|
|
CREATE INDEX idx_products_name_search ON portfolio.products
|
|
USING gin(to_tsvector('simple', name));
|
|
|
|
-- Filtering indexes
|
|
CREATE INDEX idx_products_visible ON portfolio.products(tenant_id, is_visible, status)
|
|
WHERE is_visible = TRUE AND deleted_at IS NULL;
|
|
CREATE INDEX idx_products_featured ON portfolio.products(tenant_id, is_featured)
|
|
WHERE is_featured = TRUE AND deleted_at IS NULL;
|
|
|
|
-- Price range queries
|
|
CREATE INDEX idx_products_price ON portfolio.products(tenant_id, base_price);
|
|
|
|
-- Inventory queries
|
|
CREATE INDEX idx_products_low_stock ON portfolio.products(tenant_id, stock_quantity)
|
|
WHERE track_inventory = TRUE AND deleted_at IS NULL;
|
|
CREATE INDEX idx_products_out_of_stock ON portfolio.products(tenant_id)
|
|
WHERE track_inventory = TRUE AND stock_quantity <= 0 AND deleted_at IS NULL;
|
|
|
|
-- Soft delete filter
|
|
CREATE INDEX idx_products_active ON portfolio.products(tenant_id)
|
|
WHERE deleted_at IS NULL;
|
|
|
|
-- Catalog view (common query pattern)
|
|
CREATE INDEX idx_products_catalog ON portfolio.products(tenant_id, category_id, status, base_price)
|
|
WHERE deleted_at IS NULL AND is_visible = TRUE;
|
|
|
|
-- ============================================
|
|
-- Variants Indexes
|
|
-- ============================================
|
|
CREATE INDEX idx_variants_tenant ON portfolio.variants(tenant_id);
|
|
CREATE INDEX idx_variants_product ON portfolio.variants(product_id);
|
|
CREATE INDEX idx_variants_sku ON portfolio.variants(tenant_id, sku) WHERE sku IS NOT NULL;
|
|
CREATE INDEX idx_variants_position ON portfolio.variants(product_id, position);
|
|
|
|
-- Inventory queries
|
|
CREATE INDEX idx_variants_stock ON portfolio.variants(tenant_id, stock_quantity);
|
|
|
|
-- Active variants
|
|
CREATE INDEX idx_variants_active ON portfolio.variants(product_id, is_active)
|
|
WHERE is_active = TRUE AND deleted_at IS NULL;
|
|
|
|
-- Soft delete filter
|
|
CREATE INDEX idx_variants_not_deleted ON portfolio.variants(tenant_id)
|
|
WHERE deleted_at IS NULL;
|
|
|
|
-- ============================================
|
|
-- Prices Indexes
|
|
-- ============================================
|
|
CREATE INDEX idx_prices_tenant ON portfolio.prices(tenant_id);
|
|
CREATE INDEX idx_prices_product ON portfolio.prices(product_id) WHERE product_id IS NOT NULL;
|
|
CREATE INDEX idx_prices_variant ON portfolio.prices(variant_id) WHERE variant_id IS NOT NULL;
|
|
CREATE INDEX idx_prices_currency ON portfolio.prices(tenant_id, currency);
|
|
CREATE INDEX idx_prices_type ON portfolio.prices(tenant_id, price_type);
|
|
|
|
-- Active prices
|
|
CREATE INDEX idx_prices_active ON portfolio.prices(tenant_id, is_active)
|
|
WHERE is_active = TRUE AND deleted_at IS NULL;
|
|
|
|
-- Time-based price queries
|
|
CREATE INDEX idx_prices_validity ON portfolio.prices(tenant_id, valid_from, valid_until)
|
|
WHERE is_active = TRUE AND deleted_at IS NULL;
|
|
|
|
-- Priority for price selection
|
|
CREATE INDEX idx_prices_priority ON portfolio.prices(product_id, currency, priority DESC)
|
|
WHERE is_active = TRUE AND deleted_at IS NULL;
|
|
|
|
-- Soft delete filter
|
|
CREATE INDEX idx_prices_not_deleted ON portfolio.prices(tenant_id)
|
|
WHERE deleted_at IS NULL;
|
|
|
|
-- ============================================
|
|
-- Composite indexes for common queries
|
|
-- ============================================
|
|
|
|
-- Product listing with category
|
|
CREATE INDEX idx_products_category_listing ON portfolio.products(tenant_id, category_id, status, position)
|
|
WHERE deleted_at IS NULL AND is_visible = TRUE;
|
|
|
|
-- Product search by tags
|
|
CREATE INDEX idx_products_tags ON portfolio.products USING gin(tags);
|
|
|
|
-- Variant lookup for product
|
|
CREATE INDEX idx_variants_product_active ON portfolio.variants(product_id, position)
|
|
WHERE is_active = TRUE AND deleted_at IS NULL;
|
|
|
|
-- Price lookup for product + currency
|
|
CREATE INDEX idx_prices_product_currency ON portfolio.prices(product_id, currency, priority DESC, valid_from)
|
|
WHERE is_active = TRUE AND deleted_at IS NULL AND product_id IS NOT NULL;
|