template-saas-database-v2/ddl/schemas/portfolio/05-indexes.sql
Adrian Flores Cortes a3f354528a [SAAS-019] feat: Add Portfolio module DDL
- 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>
2026-01-25 05:43:02 -06:00

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;