setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo "✅ Database connection established\n\n"; $service = new MaterializedViewService($pdo); // Cleanup echo "Cleanup...\n"; $pdo->exec("DROP TABLE IF EXISTS test_sales CASCADE"); $pdo->exec("DROP MATERIALIZED VIEW IF EXISTS sales_summary"); $pdo->exec("DROP MATERIALIZED VIEW IF EXISTS top_products"); echo "✅ Cleanup complete\n\n"; // Create test table echo "Test 1: Create Test Data\n"; echo "=========================\n"; $pdo->exec(" CREATE TABLE test_sales ( id SERIAL PRIMARY KEY, product_name VARCHAR(100), category VARCHAR(50), amount NUMERIC(10,2), sale_date DATE ) "); $pdo->exec(" INSERT INTO test_sales (product_name, category, amount, sale_date) VALUES ('Laptop', 'Electronics', 1200.00, '2025-01-10'), ('Mouse', 'Electronics', 25.00, '2025-01-10'), ('Desk', 'Furniture', 350.00, '2025-01-11'), ('Chair', 'Furniture', 150.00, '2025-01-11'), ('Keyboard', 'Electronics', 75.00, '2025-01-12') "); echo "✅ Test table created with 5 sales records\n\n"; // Test 2: Create Materialized View echo "Test 2: Create Materialized View\n"; echo "=================================\n"; $view = new MaterializedView( 'sales_summary', "SELECT category, COUNT(*) as total_sales, SUM(amount) as total_amount FROM test_sales GROUP BY category" ); $service->create($view); echo "✅ Materialized view 'sales_summary' created\n"; // Query materialized view $stmt = $pdo->query("SELECT * FROM sales_summary ORDER BY category"); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); echo " Initial data:\n"; foreach ($results as $row) { echo " - {$row['category']}: {$row['total_sales']} sales, Total: €{$row['total_amount']}\n"; } echo "\n"; // Test 3: Add more data (materialized view doesn't auto-update) echo "Test 3: Add Data (View Doesn't Auto-Update)\n"; echo "============================================\n"; $pdo->exec("INSERT INTO test_sales (product_name, category, amount, sale_date) VALUES ('Monitor', 'Electronics', 300.00, '2025-01-13')"); echo "✅ Added new sale (Electronics, €300)\n"; $stmt = $pdo->query("SELECT * FROM sales_summary WHERE category = 'Electronics'"); $before = $stmt->fetch(PDO::FETCH_ASSOC); echo " Electronics BEFORE refresh: {$before['total_sales']} sales, €{$before['total_amount']}\n"; echo " (Should still show old data)\n\n"; // Test 4: Refresh Materialized View echo "Test 4: REFRESH Materialized View\n"; echo "==================================\n"; $service->refresh('sales_summary'); echo "✅ Materialized view refreshed\n"; $stmt = $pdo->query("SELECT * FROM sales_summary WHERE category = 'Electronics'"); $after = $stmt->fetch(PDO::FETCH_ASSOC); echo " Electronics AFTER refresh: {$after['total_sales']} sales, €{$after['total_amount']}\n"; echo ($after['total_amount'] > $before['total_amount']) ? "✅ Data updated after refresh\n" : "❌ Should have updated\n"; echo "\n"; // Test 5: Create view with index (for CONCURRENTLY refresh) echo "Test 5: View With Index (Concurrent Refresh)\n"; echo "=============================================\n"; $topProductsView = new MaterializedView( 'top_products', "SELECT product_name, amount FROM test_sales ORDER BY amount DESC LIMIT 3" ); $service->create($topProductsView); echo "✅ Materialized view 'top_products' created\n"; // Create unique index (required for CONCURRENTLY) $pdo->exec("CREATE UNIQUE INDEX top_products_idx ON top_products (product_name)"); echo "✅ Unique index created\n"; // Concurrent refresh $service->refresh('top_products', concurrently: true); echo "✅ Concurrent refresh successful\n\n"; // Test 6: List all materialized views echo "Test 6: List All Materialized Views\n"; echo "====================================\n"; $views = $service->listAll(); echo "✅ Found " . count($views) . " materialized views:\n"; foreach ($views as $v) { echo " - {$v['name']} (has_indexes: " . ($v['has_indexes'] ? 'yes' : 'no') . ")\n"; } echo "\n"; // Test 7: exists() check echo "Test 7: exists() Check\n"; echo "======================\n"; echo $service->exists('sales_summary') ? "✅ sales_summary exists\n" : "❌ Should exist\n"; echo !$service->exists('non_existent') ? "✅ non_existent doesn't exist\n" : "❌ Should not exist\n"; echo "\n"; // Cleanup echo "Cleanup...\n"; $pdo->exec("DROP TABLE IF EXISTS test_sales CASCADE"); echo "✅ Test data cleaned up\n"; echo "\n✅ All Materialized View tests passed!\n"; echo "\nSummary:\n"; echo "========\n"; echo "✅ CREATE MATERIALIZED VIEW works\n"; echo "✅ Materialized views store computed results\n"; echo "✅ REFRESH MATERIALIZED VIEW updates data\n"; echo "✅ REFRESH ... CONCURRENTLY works with unique index\n"; echo "✅ Listing and checking existence works\n"; } catch (\Exception $e) { echo "❌ Error: " . $e->getMessage() . "\n"; echo "Stack trace:\n" . $e->getTraceAsString() . "\n"; exit(1); }