hirejared-kw-db/docs/project-docs/03-scripts/table-admin/create-tables.md
2024-11-19 07:52:08 -05:00

274 lines
7.8 KiB
Markdown

# 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
```sql
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
```bash
#!/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
```sql
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
```sql
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
```sql
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
```sql
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
```sql
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:
```bash
#!/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