7.8 KiB
7.8 KiB
Table Creation Scripts Documentation
Overview
These scripts handle the creation of all database tables for the keyword management system. Each table has its own creation script to maintain modularity and allow for independent testing.
Script Locations
/bin/table-admin/create-tables/
├── create-keywords-table.sh
├── create-campaigns-table.sh
├── create-landing-pages-table.sh
├── create-ad-groups-table.sh
├── create-keyword-assignments-table.sh
└── create-import-history-table.sh
Keywords Table Script
Location
/bin/table-admin/create-tables/create-keywords-table.sh
SQL Command
CREATE TABLE Keywords (
keyword_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
keyword VARCHAR(255) NOT NULL,
-- GKWP Data
gkwp_search_volume INTEGER,
gkwp_competition_index INTEGER,
gkwp_cpc_min DECIMAL(10,2),
gkwp_cpc_max DECIMAL(10,2),
gkwp_last_updated TIMESTAMP,
-- SEMRush Data
semrush_search_volume INTEGER,
semrush_difficulty INTEGER,
semrush_cpc DECIMAL(10,2),
semrush_intent VARCHAR(50),
semrush_last_updated TIMESTAMP,
-- Metadata
first_imported TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Case-insensitive unique constraint
CREATE UNIQUE INDEX unique_lowercase_keyword
ON Keywords (LOWER(keyword));
Implementation
#!/bin/bash
# Load configuration
source ../../../.database
# Set error handling
set -e
# Setup logging
LOG_DIR="../../../logs"
LOG_FILE="${LOG_DIR}/$(date +%Y-%m-%d)-create-keywords-table.log"
mkdir -p "$LOG_DIR"
# Function to log messages
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Check if table exists
TABLE_EXISTS=$(psql -h "${DB_HOST}" \
-p "${DB_PORT}" \
-U "${DB_USER}" \
-d "${DB_NAME}" \
-tAc "SELECT to_regclass('public.keywords');")
if [ "$TABLE_EXISTS" == "keywords" ]; then
log_message "Error: Keywords table already exists"
exit 1
fi
# Create table
log_message "Creating Keywords table..."
psql -h "${DB_HOST}" \
-p "${DB_PORT}" \
-U "${DB_USER}" \
-d "${DB_NAME}" \
-f "sql/create-keywords-table.sql"
# Verify creation
if [ $? -eq 0 ]; then
log_message "Keywords table created successfully"
# Log table structure
log_message "Table structure:"
psql -h "${DB_HOST}" \
-p "${DB_PORT}" \
-U "${DB_USER}" \
-d "${DB_NAME}" \
-c "\d+ keywords" >> "$LOG_FILE"
else
log_message "Error: Failed to create Keywords table"
exit 1
fi
Campaigns Table Script
Location
/bin/table-admin/create-tables/create-campaigns-table.sh
SQL Command
CREATE TABLE Campaigns (
campaign_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
campaign_name VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'active',
start_date DATE,
end_date DATE,
budget_daily DECIMAL(10,2),
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_campaign_name UNIQUE(campaign_name)
);
Landing Pages Table Script
Location
/bin/table-admin/create-tables/create-landing-pages-table.sh
SQL Command
CREATE TABLE Landing_Pages (
landing_page_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
url VARCHAR(2048) NOT NULL,
page_name VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'active',
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_url UNIQUE(url),
CONSTRAINT unique_page_name UNIQUE(page_name)
);
Ad Groups Table Script
Location
/bin/table-admin/create-tables/create-ad-groups-table.sh
SQL Command
CREATE TABLE Ad_Groups (
ad_group_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
campaign_id INTEGER NOT NULL,
landing_page_id INTEGER NOT NULL,
ad_group_name VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'active',
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_campaign
FOREIGN KEY (campaign_id)
REFERENCES Campaigns(campaign_id),
CONSTRAINT fk_landing_page
FOREIGN KEY (landing_page_id)
REFERENCES Landing_Pages(landing_page_id),
CONSTRAINT unique_ad_group_name_per_campaign
UNIQUE(campaign_id, ad_group_name)
);
Keyword Assignments Table Script
Location
/bin/table-admin/create-tables/create-keyword-assignments-table.sh
SQL Command
CREATE TABLE Keyword_Ad_Group_Assignments (
keyword_id INTEGER NOT NULL,
ad_group_id INTEGER NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'active',
assigned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
notes TEXT,
PRIMARY KEY (keyword_id, ad_group_id),
FOREIGN KEY (keyword_id) REFERENCES Keywords(keyword_id),
FOREIGN KEY (ad_group_id) REFERENCES Ad_Groups(ad_group_id)
);
Import History Table Script
Location
/bin/table-admin/create-tables/create-import-history-table.sh
SQL Command
CREATE TABLE Import_History (
import_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
import_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
source_type VARCHAR(50) NOT NULL,
filename VARCHAR(255),
original_seed_keyword VARCHAR(255),
assigned_ad_group_id INTEGER,
row_count INTEGER,
success_count INTEGER,
error_count INTEGER,
import_status VARCHAR(50) NOT NULL,
error_details TEXT,
notes TEXT,
FOREIGN KEY (assigned_ad_group_id) REFERENCES Ad_Groups(ad_group_id)
);
Testing
Located in /tests/table-admin/create-tables/
Each table has its own test file:
/tests/table-admin/create-tables/
├── create-keywords-table.test.sh
├── create-campaigns-table.test.sh
├── create-landing-pages-table.test.sh
├── create-ad-groups-table.test.sh
├── create-keyword-assignments-table.test.sh
└── create-import-history-table.test.sh
Example test for Keywords table:
#!/bin/bash
source ../../utils/test-framework.sh
test_keywords_table_creation() {
# Ensure table doesn't exist
psql -d "${DB_NAME}" -c "DROP TABLE IF EXISTS Keywords CASCADE;"
# Create table
../bin/table-admin/create-tables/create-keywords-table.sh
# Verify table exists
exists_check=$(psql -tAc "SELECT to_regclass('public.keywords');" "${DB_NAME}")
assert_equals "$exists_check" "keywords" "Keywords table should exist"
# Verify columns
columns=$(psql -tAc "\d keywords" "${DB_NAME}")
assert_contains "$columns" "keyword_id" "Should have keyword_id column"
assert_contains "$columns" "keyword" "Should have keyword column"
# Test unique constraint
psql -d "${DB_NAME}" -c "INSERT INTO Keywords (keyword) VALUES ('Test');"
error_check=$(psql -d "${DB_NAME}" -c "INSERT INTO Keywords (keyword) VALUES ('TEST');" 2>&1)
assert_contains "$error_check" "duplicate key value" "Should enforce case-insensitive uniqueness"
}
run_test_suite
Notes
- Tables must be created in the correct order due to foreign key constraints
- Each script includes proper error handling and logging
- Case-insensitive keyword storage is enforced
- All timestamp fields use timezone-free TIMESTAMP type
- Status fields use predefined values
- Each table has appropriate indexes for performance