153 lines
4.8 KiB
JavaScript
153 lines
4.8 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
const { pool, query } = require("./config/database");
|
|||
|
|
|
|||
|
|
async function analyzeSchema() {
|
|||
|
|
console.log("🔬 Analyzing Database Schema...\n");
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 1. Check products table columns
|
|||
|
|
console.log("1️⃣ Products Table Structure:");
|
|||
|
|
const productCols = await query(`
|
|||
|
|
SELECT column_name, data_type, is_nullable, column_default
|
|||
|
|
FROM information_schema.columns
|
|||
|
|
WHERE table_name = 'products'
|
|||
|
|
ORDER BY ordinal_position
|
|||
|
|
`);
|
|||
|
|
productCols.rows.forEach((col) => {
|
|||
|
|
const nullable = col.is_nullable === "YES" ? "(nullable)" : "(NOT NULL)";
|
|||
|
|
console.log(
|
|||
|
|
` ${col.column_name.padEnd(20)} ${col.data_type.padEnd(
|
|||
|
|
25
|
|||
|
|
)} ${nullable}`
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 2. Check products indexes
|
|||
|
|
console.log("\n2️⃣ Products Table Indexes:");
|
|||
|
|
const productIndexes = await query(`
|
|||
|
|
SELECT indexname, indexdef
|
|||
|
|
FROM pg_indexes
|
|||
|
|
WHERE tablename = 'products'
|
|||
|
|
ORDER BY indexname
|
|||
|
|
`);
|
|||
|
|
productIndexes.rows.forEach((idx) => {
|
|||
|
|
console.log(` ${idx.indexname}`);
|
|||
|
|
console.log(` ${idx.indexdef.substring(0, 80)}...`);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 3. Check portfolio projects structure
|
|||
|
|
console.log("\n3️⃣ Portfolio Projects Structure:");
|
|||
|
|
const portfolioCols = await query(`
|
|||
|
|
SELECT column_name, data_type, is_nullable
|
|||
|
|
FROM information_schema.columns
|
|||
|
|
WHERE table_name = 'portfolioprojects'
|
|||
|
|
ORDER BY ordinal_position
|
|||
|
|
`);
|
|||
|
|
portfolioCols.rows.forEach((col) => {
|
|||
|
|
const nullable = col.is_nullable === "YES" ? "(nullable)" : "(NOT NULL)";
|
|||
|
|
console.log(
|
|||
|
|
` ${col.column_name.padEnd(20)} ${col.data_type.padEnd(
|
|||
|
|
25
|
|||
|
|
)} ${nullable}`
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 4. Check portfolio indexes
|
|||
|
|
console.log("\n4️⃣ Portfolio Projects Indexes:");
|
|||
|
|
const portfolioIndexes = await query(`
|
|||
|
|
SELECT indexname, indexdef
|
|||
|
|
FROM pg_indexes
|
|||
|
|
WHERE tablename = 'portfolioprojects'
|
|||
|
|
`);
|
|||
|
|
console.log(` Total: ${portfolioIndexes.rows.length} indexes`);
|
|||
|
|
portfolioIndexes.rows.forEach((idx) => {
|
|||
|
|
console.log(` - ${idx.indexname}`);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 5. Check blogposts indexes
|
|||
|
|
console.log("\n5️⃣ Blog Posts Indexes:");
|
|||
|
|
const blogIndexes = await query(`
|
|||
|
|
SELECT indexname, indexdef
|
|||
|
|
FROM pg_indexes
|
|||
|
|
WHERE tablename = 'blogposts'
|
|||
|
|
`);
|
|||
|
|
blogIndexes.rows.forEach((idx) => {
|
|||
|
|
console.log(` - ${idx.indexname}`);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 6. Check pages indexes
|
|||
|
|
console.log("\n6️⃣ Pages Indexes:");
|
|||
|
|
const pagesIndexes = await query(`
|
|||
|
|
SELECT indexname, indexdef
|
|||
|
|
FROM pg_indexes
|
|||
|
|
WHERE tablename = 'pages'
|
|||
|
|
`);
|
|||
|
|
pagesIndexes.rows.forEach((idx) => {
|
|||
|
|
console.log(` - ${idx.indexname}`);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 7. Check product_images foreign key
|
|||
|
|
console.log("\n7️⃣ Product Images Foreign Keys:");
|
|||
|
|
const piFks = await query(`
|
|||
|
|
SELECT
|
|||
|
|
tc.constraint_name,
|
|||
|
|
kcu.column_name,
|
|||
|
|
ccu.table_name AS foreign_table,
|
|||
|
|
rc.delete_rule,
|
|||
|
|
rc.update_rule
|
|||
|
|
FROM information_schema.table_constraints AS tc
|
|||
|
|
JOIN information_schema.key_column_usage AS kcu
|
|||
|
|
ON tc.constraint_name = kcu.constraint_name
|
|||
|
|
JOIN information_schema.constraint_column_usage AS ccu
|
|||
|
|
ON ccu.constraint_name = tc.constraint_name
|
|||
|
|
JOIN information_schema.referential_constraints AS rc
|
|||
|
|
ON tc.constraint_name = rc.constraint_name
|
|||
|
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|||
|
|
AND tc.table_name = 'product_images'
|
|||
|
|
`);
|
|||
|
|
if (piFks.rows.length === 0) {
|
|||
|
|
console.log(" ⚠️ No foreign keys found!");
|
|||
|
|
} else {
|
|||
|
|
piFks.rows.forEach((fk) => {
|
|||
|
|
console.log(
|
|||
|
|
` ${fk.column_name} → ${fk.foreign_table} (DELETE: ${fk.delete_rule})`
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 8. Check unique constraints
|
|||
|
|
console.log("\n8️⃣ Unique Constraints:");
|
|||
|
|
const uniqueConstraints = await query(`
|
|||
|
|
SELECT
|
|||
|
|
tc.table_name,
|
|||
|
|
tc.constraint_name,
|
|||
|
|
kcu.column_name
|
|||
|
|
FROM information_schema.table_constraints tc
|
|||
|
|
JOIN information_schema.key_column_usage kcu
|
|||
|
|
ON tc.constraint_name = kcu.constraint_name
|
|||
|
|
WHERE tc.constraint_type = 'UNIQUE'
|
|||
|
|
AND tc.table_schema = 'public'
|
|||
|
|
AND tc.table_name IN ('products', 'blogposts', 'pages', 'portfolioprojects')
|
|||
|
|
ORDER BY tc.table_name, tc.constraint_name
|
|||
|
|
`);
|
|||
|
|
if (uniqueConstraints.rows.length === 0) {
|
|||
|
|
console.log(" ⚠️ No unique constraints on slug columns!");
|
|||
|
|
} else {
|
|||
|
|
uniqueConstraints.rows.forEach((uc) => {
|
|||
|
|
console.log(
|
|||
|
|
` ${uc.table_name}.${uc.column_name} (${uc.constraint_name})`
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log("\n✅ Analysis complete!");
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error("❌ Error:", error.message);
|
|||
|
|
console.error(error);
|
|||
|
|
} finally {
|
|||
|
|
await pool.end();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
analyzeSchema();
|