CRITICAL FIXES: - Added 'sites' table (SUPER PARENT) - referenced by 10+ tables - Added 'campaign_masters' table - referenced by 3 tables - Fixed field names: campaign → campaign_id, site → site_id - Organized schema into dependency batches (Batch 1→2→3) This fixes the root cause of foreign key constraint failures.
412 lines
13 KiB
SQL
412 lines
13 KiB
SQL
-- Complete Spark Platform Database Schema
|
|
-- Creates all remaining tables with proper relationships
|
|
|
|
-- ============================================
|
|
-- BATCH 1: PARENT TABLES (NO DEPENDENCIES)
|
|
-- These MUST be created first as other tables reference them
|
|
-- ============================================
|
|
|
|
-- Super Parent #1: Sites - Referenced by 10+ tables
|
|
CREATE TABLE IF NOT EXISTS sites (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255) NOT NULL,
|
|
url VARCHAR(500),
|
|
domain VARCHAR(255),
|
|
status VARCHAR(50) DEFAULT 'active',
|
|
wp_url VARCHAR(500),
|
|
wp_username VARCHAR(255),
|
|
wp_app_password TEXT,
|
|
site_globals JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
date_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Super Parent #2: Campaign Masters - Referenced by headline_inventory, content_fragments
|
|
CREATE TABLE IF NOT EXISTS campaign_masters (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site_id UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
name VARCHAR(255) NOT NULL,
|
|
headline_spintax_root TEXT,
|
|
niche_variables JSONB,
|
|
location_mode VARCHAR(100),
|
|
location_target VARCHAR(255),
|
|
batch_count INTEGER DEFAULT 0,
|
|
status VARCHAR(50) DEFAULT 'active',
|
|
target_word_count INTEGER DEFAULT 1500,
|
|
article_template UUID,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- BATCH 2: CONTENT FACTORY / SEO ENGINE
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS headline_inventory (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
campaign_id UUID REFERENCES campaign_masters (id) ON DELETE CASCADE,
|
|
final_title_text VARCHAR(500),
|
|
status VARCHAR(50) DEFAULT 'available',
|
|
used_on_article UUID,
|
|
location_data JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS content_fragments (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
campaign UUID REFERENCES campaign_masters (id) ON DELETE CASCADE,
|
|
fragment_type VARCHAR(100),
|
|
content_body TEXT,
|
|
word_count INTEGER,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS production_queue (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site_id UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
campaign_id UUID REFERENCES campaign_masters (id) ON DELETE CASCADE,
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|
total_requested INTEGER,
|
|
completed_count INTEGER DEFAULT 0,
|
|
velocity_mode VARCHAR(50),
|
|
schedule_data JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS quality_flags (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
batch_id VARCHAR(255),
|
|
article_a VARCHAR(255),
|
|
article_b VARCHAR(255),
|
|
collision_text TEXT,
|
|
similarity_score FLOAT,
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- CARTESIAN ENGINE
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS generation_jobs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site_id UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
target_quantity INTEGER,
|
|
status VARCHAR(50) DEFAULT 'queued',
|
|
type VARCHAR(100),
|
|
progress INTEGER DEFAULT 0,
|
|
priority VARCHAR(50) DEFAULT 'medium',
|
|
config JSONB,
|
|
current_offset INTEGER DEFAULT 0,
|
|
filters JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS article_templates (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
structure_json JSONB,
|
|
description TEXT,
|
|
is_default BOOLEAN DEFAULT false,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS cartesian_patterns (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
pattern_key VARCHAR(255) UNIQUE,
|
|
pattern_type VARCHAR(100),
|
|
formula TEXT,
|
|
data JSONB,
|
|
example_output TEXT,
|
|
description TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS spintax_dictionaries (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
category VARCHAR(255),
|
|
data JSONB,
|
|
base_word VARCHAR(255),
|
|
variations TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- INTELLIGENCE LIBRARY
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS avatar_variants (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
avatar_id VARCHAR(255),
|
|
avatar_key VARCHAR(255),
|
|
variant_type VARCHAR(100),
|
|
variants_json JSONB,
|
|
data JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS avatars (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
slug VARCHAR(255) UNIQUE,
|
|
description TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- GEO INTELLIGENCE (with hierarchical relationships)
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS locations_states (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
code VARCHAR(2) UNIQUE,
|
|
population INTEGER,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS locations_counties (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
state UUID REFERENCES locations_states (id) ON DELETE CASCADE,
|
|
fips_code VARCHAR(10),
|
|
population INTEGER,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS locations_cities (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
state UUID REFERENCES locations_states (id) ON DELETE CASCADE,
|
|
county UUID REFERENCES locations_counties (id) ON DELETE SET NULL,
|
|
population INTEGER,
|
|
zip_codes JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS geo_clusters (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
cluster_key VARCHAR(255) UNIQUE,
|
|
name VARCHAR(255),
|
|
state VARCHAR(255),
|
|
description TEXT,
|
|
data JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS geo_locations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
cluster UUID REFERENCES geo_clusters (id) ON DELETE CASCADE,
|
|
city VARCHAR(255),
|
|
state VARCHAR(255),
|
|
zip VARCHAR(10),
|
|
population INTEGER,
|
|
coordinates JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS geo_intelligence (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
cluster_key VARCHAR(255),
|
|
data JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- OFFER BLOCKS
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS offer_blocks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
block_id VARCHAR(255),
|
|
title VARCHAR(255),
|
|
hook_generator TEXT,
|
|
universal_pains JSONB,
|
|
universal_solutions JSONB,
|
|
universal_value_points JSONB,
|
|
cta_spintax TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS offer_blocks_universal (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
block_id VARCHAR(255),
|
|
title VARCHAR(255),
|
|
hook_generator TEXT,
|
|
universal_pains JSONB,
|
|
universal_solutions JSONB,
|
|
universal_value_points JSONB,
|
|
cta_spintax TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- MEDIA & TEMPLATES
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS image_templates (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
svg_template TEXT,
|
|
svg_source TEXT,
|
|
is_default BOOLEAN DEFAULT false,
|
|
preview VARCHAR(255),
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- ANALYTICS & TRACKING
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS conversions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
lead UUID,
|
|
conversion_type VARCHAR(100),
|
|
value FLOAT,
|
|
currency VARCHAR(10) DEFAULT 'USD',
|
|
source VARCHAR(255),
|
|
sent_to_google BOOLEAN DEFAULT false,
|
|
sent_to_facebook BOOLEAN DEFAULT false,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS site_analytics (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
google_ads_id VARCHAR(255),
|
|
google_ads_conversion_label VARCHAR(255),
|
|
fb_pixel_id VARCHAR(255),
|
|
fb_access_token TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- INFRASTRUCTURE
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS hub_pages (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
title VARCHAR(255),
|
|
slug VARCHAR(255),
|
|
parent_hub UUID REFERENCES hub_pages (id) ON DELETE SET NULL,
|
|
level INTEGER DEFAULT 0,
|
|
articles_count INTEGER DEFAULT 0,
|
|
schema_json JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS link_targets (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
target_url VARCHAR(500),
|
|
anchor_text VARCHAR(255),
|
|
anchor_variations JSONB,
|
|
priority INTEGER DEFAULT 0,
|
|
is_active BOOLEAN DEFAULT true,
|
|
is_hub BOOLEAN DEFAULT false,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS work_log (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
action VARCHAR(255),
|
|
entity_type VARCHAR(100),
|
|
entity_id VARCHAR(255),
|
|
details JSONB,
|
|
user_id VARCHAR(255),
|
|
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- FORMS & CRM
|
|
-- ============================================
|
|
|
|
CREATE TABLE IF NOT EXISTS forms (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
name VARCHAR(255),
|
|
fields_config JSONB,
|
|
success_message TEXT,
|
|
redirect_url VARCHAR(500),
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS form_submissions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
form UUID REFERENCES forms (id) ON DELETE CASCADE,
|
|
data JSONB,
|
|
ip_address VARCHAR(50),
|
|
user_agent TEXT,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS content_modules (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
module_type VARCHAR(100),
|
|
content TEXT,
|
|
variables JSONB,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS campaigns (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
|
|
name VARCHAR(255),
|
|
site UUID REFERENCES sites (id) ON DELETE CASCADE,
|
|
status VARCHAR(50) DEFAULT 'active',
|
|
start_date TIMESTAMP,
|
|
end_date TIMESTAMP,
|
|
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- CREATE INDEXES FOR PERFORMANCE
|
|
-- ============================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_generated_articles_site ON generated_articles (site_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_generated_articles_campaign ON generated_articles (campaign_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_generated_articles_status ON generated_articles (status);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_pages_site ON pages (site);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_posts_site ON posts (site);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_leads_site ON leads (site);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_events_site ON events (site);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_pageviews_site ON pageviews (site);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_locations_counties_state ON locations_counties (state);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_locations_cities_state ON locations_cities (state);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_locations_cities_county ON locations_cities (county);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_geo_locations_cluster ON geo_locations (cluster);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hub_pages_site ON hub_pages (site);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hub_pages_parent ON hub_pages (parent_hub);
|
|
|
|
-- ============================================
|
|
-- VERIFY
|
|
-- ============================================
|
|
|
|
SELECT
|
|
COUNT(*) as total_tables,
|
|
STRING_AGG (
|
|
tablename,
|
|
', '
|
|
ORDER BY tablename
|
|
) as table_names
|
|
FROM pg_tables
|
|
WHERE
|
|
schemaname = 'public'
|
|
AND tablename NOT LIKE 'directus_%'
|
|
AND tablename NOT LIKE 'spatial_%'; |