chore: add production database cleanup scripts
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
"db:setup-dev:clean": "DATABASE_URL=\"postgresql://euchre_camp:LINGO5row_hiding@dhg.lol:5432/euchre_camp_dev\" node scripts/setup-postgres.js --drop",
|
"db:setup-dev:clean": "DATABASE_URL=\"postgresql://euchre_camp:LINGO5row_hiding@dhg.lol:5432/euchre_camp_dev\" node scripts/setup-postgres.js --drop",
|
||||||
"db:reset-dev": "node scripts/reset-dev-db.js",
|
"db:reset-dev": "node scripts/reset-dev-db.js",
|
||||||
"db:use-dev": "node scripts/use-dev-db.js",
|
"db:use-dev": "node scripts/use-dev-db.js",
|
||||||
|
"db:cleanup-prod": "node scripts/cleanup-prod-db.js",
|
||||||
"db:seed": "node scripts/seed.js",
|
"db:seed": "node scripts/seed.js",
|
||||||
"docker:up": "docker-compose up -d",
|
"docker:up": "docker-compose up -d",
|
||||||
"docker:down": "docker-compose down",
|
"docker:down": "docker-compose down",
|
||||||
|
|||||||
Executable
+111
@@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for test records in production database (read-only)
|
||||||
|
* Shows what would be deleted without making any changes
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
|
||||||
|
// Database connection string
|
||||||
|
const DB_URL = 'postgresql://euchre_camp:LINGO5row_hiding@dhg.lol:5432/euchre_camp';
|
||||||
|
|
||||||
|
// Helper to run SQL and log results
|
||||||
|
function runSQL(sql, description) {
|
||||||
|
console.log(`\n🔍 ${description}...`);
|
||||||
|
try {
|
||||||
|
const result = execSync(`psql "${DB_URL}" -c "${sql}"`, { encoding: 'utf8' });
|
||||||
|
console.log(result);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Error: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to count records matching pattern
|
||||||
|
function countRecords(table, column, pattern) {
|
||||||
|
const sql = `SELECT COUNT(*) FROM ${table} WHERE ${column} LIKE '${pattern}';`;
|
||||||
|
try {
|
||||||
|
const result = execSync(`psql "${DB_URL}" -c "${sql}" -t`, { encoding: 'utf8' }).trim();
|
||||||
|
return parseInt(result);
|
||||||
|
} catch (error) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔍 Checking test records in production database');
|
||||||
|
console.log('=============================================\n');
|
||||||
|
|
||||||
|
// Count test players
|
||||||
|
const testPlayerCount = countRecords('players', 'name', '%Test%') +
|
||||||
|
countRecords('players', 'name', '%Setup%') +
|
||||||
|
countRecords('players', 'name', '%Home Test%');
|
||||||
|
console.log(`Test players found: ${testPlayerCount}`);
|
||||||
|
|
||||||
|
// Count test tournaments
|
||||||
|
const testEventCount = countRecords('events', 'name', '%Test%') +
|
||||||
|
countRecords('events', 'name', '%Setup%');
|
||||||
|
console.log(`Test tournaments found: ${testEventCount}`);
|
||||||
|
|
||||||
|
// Count test users
|
||||||
|
const testUserCount = countRecords('users', 'email', '%test%') +
|
||||||
|
countRecords('users', 'email', '%setup%');
|
||||||
|
console.log(`Test users found: ${testUserCount}`);
|
||||||
|
|
||||||
|
// Show test players
|
||||||
|
runSQL(`
|
||||||
|
SELECT id, name
|
||||||
|
FROM players
|
||||||
|
WHERE name LIKE '%Test%' OR name LIKE '%Setup%' OR name LIKE '%Home Test%'
|
||||||
|
ORDER BY name;
|
||||||
|
`, 'Test players list');
|
||||||
|
|
||||||
|
// Show test events
|
||||||
|
runSQL(`
|
||||||
|
SELECT id, name
|
||||||
|
FROM events
|
||||||
|
WHERE name LIKE '%Test%' OR name LIKE '%Setup%'
|
||||||
|
ORDER BY name;
|
||||||
|
`, 'Test events list');
|
||||||
|
|
||||||
|
// Show test users
|
||||||
|
runSQL(`
|
||||||
|
SELECT id, email, name
|
||||||
|
FROM users
|
||||||
|
WHERE email LIKE '%test%' OR email LIKE '%setup%'
|
||||||
|
ORDER BY email;
|
||||||
|
`, 'Test users list');
|
||||||
|
|
||||||
|
// Check which test players have matches
|
||||||
|
runSQL(`
|
||||||
|
SELECT p.id, p.name
|
||||||
|
FROM players p
|
||||||
|
WHERE (p.name LIKE '%Test%' OR p.name LIKE '%Setup%' OR p.name LIKE '%Home Test%')
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1 FROM matches m
|
||||||
|
WHERE m."team1P1Id" = p.id
|
||||||
|
OR m."team1P2Id" = p.id
|
||||||
|
OR m."team2P1Id" = p.id
|
||||||
|
OR m."team2P2Id" = p.id
|
||||||
|
)
|
||||||
|
ORDER BY p.name;
|
||||||
|
`, 'Test players with matches (will be preserved)');
|
||||||
|
|
||||||
|
// Check which test events have matches
|
||||||
|
runSQL(`
|
||||||
|
SELECT e.id, e.name
|
||||||
|
FROM events e
|
||||||
|
WHERE (e.name LIKE '%Test%' OR e.name LIKE '%Setup%')
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1 FROM matches m WHERE m."eventId" = e.id
|
||||||
|
)
|
||||||
|
ORDER BY e.name;
|
||||||
|
`, 'Test events with matches (will be preserved)');
|
||||||
|
|
||||||
|
console.log('\n✅ Check complete!');
|
||||||
|
console.log('\n💡 Summary:');
|
||||||
|
console.log(' - Test players without matches can be deleted');
|
||||||
|
console.log(' - Test tournaments without matches can be deleted');
|
||||||
|
console.log(' - Test users without player associations can be deleted');
|
||||||
|
console.log(' - Records with matches/associations are preserved');
|
||||||
Executable
+130
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up production database - remove test records only
|
||||||
|
*
|
||||||
|
* WARNING: This script modifies the production database.
|
||||||
|
* It only removes records that match test patterns.
|
||||||
|
* It preserves actual player data, matches, and tournaments.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
|
||||||
|
// Database connection string
|
||||||
|
const DB_URL = 'postgresql://euchre_camp:LINGO5row_hiding@dhg.lol:5432/euchre_camp';
|
||||||
|
|
||||||
|
// Helper to run SQL and log results
|
||||||
|
function runSQL(sql, description) {
|
||||||
|
console.log(`\n🔍 ${description}...`);
|
||||||
|
try {
|
||||||
|
const result = execSync(`psql "${DB_URL}" -c "${sql}"`, { encoding: 'utf8' });
|
||||||
|
console.log(result);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Error: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to run multi-line SQL
|
||||||
|
function runMultiLineSQL(sqlLines, description) {
|
||||||
|
console.log(`\n🔍 ${description}...`);
|
||||||
|
try {
|
||||||
|
const sql = sqlLines.join('\n');
|
||||||
|
const result = execSync(`psql "${DB_URL}" -c "${sql}"`, { encoding: 'utf8' });
|
||||||
|
console.log(result);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Error: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to count records matching pattern
|
||||||
|
function countRecords(table, column, pattern) {
|
||||||
|
const sql = `SELECT COUNT(*) FROM ${table} WHERE ${column} LIKE '${pattern}';`;
|
||||||
|
try {
|
||||||
|
const result = execSync(`psql "${DB_URL}" -c "${sql}" -t`, { encoding: 'utf8' }).trim();
|
||||||
|
return parseInt(result);
|
||||||
|
} catch (error) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log('🧹 Cleaning up test records from production database');
|
||||||
|
console.log('=============================================\n');
|
||||||
|
|
||||||
|
// Confirm with user
|
||||||
|
const readline = require('readline');
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
|
rl.question('⚠️ This will DELETE test records from PRODUCTION database. Continue? (y/N) ', async (answer) => {
|
||||||
|
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
||||||
|
console.log('❌ Cleanup cancelled');
|
||||||
|
rl.close();
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.close();
|
||||||
|
|
||||||
|
console.log('\n📋 Checking test records...\n');
|
||||||
|
|
||||||
|
// Count test players
|
||||||
|
const testPlayerCount = countRecords('players', 'name', '%Test%') +
|
||||||
|
countRecords('players', 'name', '%Setup%') +
|
||||||
|
countRecords('players', 'name', '%Home Test%');
|
||||||
|
console.log(`Test players found: ${testPlayerCount}`);
|
||||||
|
|
||||||
|
// Count test tournaments
|
||||||
|
const testEventCount = countRecords('events', 'name', '%Test%') +
|
||||||
|
countRecords('events', 'name', '%Setup%');
|
||||||
|
console.log(`Test tournaments found: ${testEventCount}`);
|
||||||
|
|
||||||
|
// Count test users
|
||||||
|
const testUserCount = countRecords('users', 'email', '%test%') +
|
||||||
|
countRecords('users', 'email', '%setup%');
|
||||||
|
console.log(`Test users found: ${testUserCount}`);
|
||||||
|
|
||||||
|
console.log('\n🔄 Starting cleanup...\n');
|
||||||
|
|
||||||
|
// Step 1: Delete test events (tournaments) that have no matches
|
||||||
|
console.log('1. Deleting test tournaments without matches...');
|
||||||
|
runSQL(
|
||||||
|
"DELETE FROM events WHERE (name LIKE '%Test%' OR name LIKE '%Setup%') AND NOT EXISTS (SELECT 1 FROM matches WHERE matches.\"eventId\" = events.id);",
|
||||||
|
'Deleted test tournaments'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 2: Delete test players that have no matches
|
||||||
|
console.log('\n2. Deleting test players without matches...');
|
||||||
|
runSQL(
|
||||||
|
"DELETE FROM players WHERE (name LIKE '%Test%' OR name LIKE '%Setup%' OR name LIKE '%Home Test%') AND NOT EXISTS (SELECT 1 FROM matches WHERE matches.\"team1P1Id\" = players.id) AND NOT EXISTS (SELECT 1 FROM matches WHERE matches.\"team1P2Id\" = players.id) AND NOT EXISTS (SELECT 1 FROM matches WHERE matches.\"team2P1Id\" = players.id) AND NOT EXISTS (SELECT 1 FROM matches WHERE matches.\"team2P2Id\" = players.id);",
|
||||||
|
'Deleted test players without matches'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 3: Delete test users (they shouldn't have player associations)
|
||||||
|
console.log('\n3. Deleting test users...');
|
||||||
|
runSQL(
|
||||||
|
"DELETE FROM users WHERE (email LIKE '%test%' OR email LIKE '%setup%') AND \"playerId\" IS NULL;",
|
||||||
|
'Deleted test users'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Summary
|
||||||
|
console.log('\n✅ Cleanup complete!');
|
||||||
|
console.log('\n📊 Remaining test records:');
|
||||||
|
runSQL("SELECT COUNT(*) FROM players WHERE name LIKE '%Test%' OR name LIKE '%Setup%' OR name LIKE '%Home Test%';", 'Remaining test players');
|
||||||
|
runSQL("SELECT COUNT(*) FROM events WHERE name LIKE '%Test%' OR name LIKE '%Setup%';", 'Remaining test tournaments');
|
||||||
|
runSQL("SELECT COUNT(*) FROM users WHERE email LIKE '%test%' OR email LIKE '%setup%';", 'Remaining test users');
|
||||||
|
|
||||||
|
console.log('\n💡 Note: Some test records may remain if they have:');
|
||||||
|
console.log(' - Associated matches');
|
||||||
|
console.log(' - Associated users');
|
||||||
|
console.log(' These were preserved to maintain data integrity.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run main function
|
||||||
|
main();
|
||||||
Reference in New Issue
Block a user