| """ |
| Verification script for Vector Database DBA Analysis task. |
| |
| This script verifies that the candidate has properly analyzed the vector database |
| and stored their findings in appropriate result tables. |
| """ |
|
|
| import logging |
| import psycopg2 |
| import os |
| import sys |
| from typing import Dict, Any |
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| def get_connection_params(): |
| """Get database connection parameters from environment variables.""" |
| return { |
| "host": os.getenv("POSTGRES_HOST", "localhost"), |
| "port": int(os.getenv("POSTGRES_PORT", 5432)), |
| "database": os.getenv("POSTGRES_DATABASE"), |
| "user": os.getenv("POSTGRES_USERNAME"), |
| "password": os.getenv("POSTGRES_PASSWORD"), |
| } |
|
|
|
|
| def verify_vector_analysis_columns(conn) -> Dict[str, Any]: |
| """Verify the vector_analysis_columns table exists, has correct columns, and contains actual vector columns from the database.""" |
| results = {'passed': False, 'issues': []} |
| expected_columns = [ |
| 'schema', 'table_name', 'column_name', 'dimensions', 'data_type', 'has_constraints', 'rows' |
| ] |
| try: |
| with conn.cursor() as cur: |
| |
| cur.execute(""" |
| SELECT EXISTS ( |
| SELECT FROM information_schema.tables |
| WHERE table_name = 'vector_analysis_columns' |
| ); |
| """) |
| if not cur.fetchone()[0]: |
| results['issues'].append("vector_analysis_columns table not found") |
| return results |
|
|
| |
| cur.execute(""" |
| SELECT column_name FROM information_schema.columns |
| WHERE table_name = 'vector_analysis_columns' |
| ORDER BY column_name; |
| """) |
| actual_columns = {row[0] for row in cur.fetchall()} |
| missing = set(expected_columns) - actual_columns |
| extra = actual_columns - set(expected_columns) |
| if missing: |
| results['issues'].append(f"Missing columns: {missing}") |
| if extra: |
| results['issues'].append(f"Unexpected columns: {extra}") |
|
|
| |
| cur.execute("SELECT COUNT(*) FROM vector_analysis_columns;") |
| count = cur.fetchone()[0] |
| if count == 0: |
| results['issues'].append("No rows found in vector_analysis_columns") |
| return results |
|
|
| |
| cur.execute(""" |
| SELECT table_name, column_name |
| FROM information_schema.columns |
| WHERE data_type = 'USER-DEFINED' |
| AND udt_name = 'vector' |
| ORDER BY table_name, column_name; |
| """) |
| actual_vector_columns = set(cur.fetchall()) |
|
|
| |
| cur.execute(""" |
| SELECT table_name, column_name |
| FROM vector_analysis_columns |
| ORDER BY table_name, column_name; |
| """) |
| found_vector_columns = set(cur.fetchall()) |
|
|
| |
| missing_vectors = actual_vector_columns - found_vector_columns |
| extra_vectors = found_vector_columns - actual_vector_columns |
|
|
| if missing_vectors: |
| results['issues'].append(f"Missing: {missing_vectors}") |
| if extra_vectors: |
| results['issues'].append(f"Non-existing: {extra_vectors}") |
|
|
| if not missing and not extra and count > 0 and not missing_vectors and not extra_vectors: |
| results['passed'] = True |
|
|
| except psycopg2.Error as e: |
| results['issues'].append(f"Database error: {e}") |
| except Exception as e: |
| results['issues'].append(f"Verification error: {e}") |
| return results |
|
|
|
|
| def verify_vector_analysis_storage_consumption(conn) -> Dict[str, Any]: |
| """Verify the vector_analysis_storage_consumption table exists, has correct columns, and analyzes actual vector tables.""" |
| results = {'passed': False, 'issues': []} |
| expected_columns = [ |
| 'schema', 'table_name', 'total_size_bytes', 'vector_data_bytes', 'regular_data_bytes', 'vector_storage_pct', 'row_count' |
| ] |
| try: |
| with conn.cursor() as cur: |
| cur.execute(""" |
| SELECT EXISTS ( |
| SELECT FROM information_schema.tables |
| WHERE table_name = 'vector_analysis_storage_consumption' |
| ); |
| """) |
| if not cur.fetchone()[0]: |
| results['issues'].append("vector_analysis_storage_consumption table not found") |
| return results |
|
|
| cur.execute(""" |
| SELECT column_name FROM information_schema.columns |
| WHERE table_name = 'vector_analysis_storage_consumption' |
| ORDER BY column_name; |
| """) |
| actual_columns = {row[0] for row in cur.fetchall()} |
| missing = set(expected_columns) - actual_columns |
| extra = actual_columns - set(expected_columns) |
| if missing: |
| results['issues'].append(f"Missing columns: {missing}") |
| if extra: |
| results['issues'].append(f"Unexpected columns: {extra}") |
|
|
| cur.execute("SELECT COUNT(*) FROM vector_analysis_storage_consumption;") |
| count = cur.fetchone()[0] |
| if count == 0: |
| results['issues'].append("No rows found in vector_analysis_storage_consumption") |
| return results |
|
|
| |
| cur.execute(""" |
| SELECT DISTINCT table_name |
| FROM information_schema.columns |
| WHERE data_type = 'USER-DEFINED' |
| AND udt_name = 'vector' |
| ORDER BY table_name; |
| """) |
| actual_vector_tables = {row[0] for row in cur.fetchall()} |
|
|
| |
| cur.execute(""" |
| SELECT DISTINCT table_name |
| FROM vector_analysis_storage_consumption |
| ORDER BY table_name; |
| """) |
| analyzed_tables = {row[0] for row in cur.fetchall()} |
|
|
| |
| missing_tables = actual_vector_tables - analyzed_tables |
| if missing_tables: |
| results['issues'].append(f"Agent missed analyzing vector tables: {missing_tables}") |
|
|
| |
| extra_tables = analyzed_tables - actual_vector_tables |
| if extra_tables: |
| results['issues'].append(f"Agent analyzed non-vector tables: {extra_tables}") |
|
|
| if not missing and not extra and count > 0 and not missing_tables and not extra_tables: |
| results['passed'] = True |
|
|
| except psycopg2.Error as e: |
| results['issues'].append(f"Database error: {e}") |
| except Exception as e: |
| results['issues'].append(f"Verification error: {e}") |
| return results |
|
|
|
|
| def verify_vector_analysis_indices(conn) -> Dict[str, Any]: |
| """Verify the vector_analysis_indices table exists, has correct columns, and identifies actual vector indexes.""" |
| results = {'passed': False, 'issues': []} |
| expected_columns = [ |
| 'schema', 'table_name', 'column_name', 'index_name', 'index_type', 'index_size_bytes' |
| ] |
| try: |
| with conn.cursor() as cur: |
| cur.execute(""" |
| SELECT EXISTS ( |
| SELECT FROM information_schema.tables |
| WHERE table_name = 'vector_analysis_indices' |
| ); |
| """) |
| if not cur.fetchone()[0]: |
| results['issues'].append("vector_analysis_indices table not found") |
| return results |
|
|
| cur.execute(""" |
| SELECT column_name FROM information_schema.columns |
| WHERE table_name = 'vector_analysis_indices' |
| ORDER BY column_name; |
| """) |
| actual_columns = {row[0] for row in cur.fetchall()} |
| missing = set(expected_columns) - actual_columns |
| extra = actual_columns - set(expected_columns) |
| if missing: |
| results['issues'].append(f"Missing columns: {missing}") |
| if extra: |
| results['issues'].append(f"Unexpected columns: {extra}") |
|
|
| cur.execute("SELECT COUNT(*) FROM vector_analysis_indices;") |
| count = cur.fetchone()[0] |
| if count == 0: |
| results['issues'].append("No rows found in vector_analysis_indices") |
| return results |
|
|
| |
| cur.execute(""" |
| SELECT schemaname, tablename, indexname |
| FROM pg_indexes |
| WHERE (indexdef ILIKE '%hnsw%' OR indexdef ILIKE '%ivfflat%') |
| AND tablename NOT LIKE '%analysis%' |
| ORDER BY tablename, indexname; |
| """) |
| actual_vector_indexes = set(cur.fetchall()) |
|
|
| |
| cur.execute(""" |
| SELECT schema, table_name, index_name |
| FROM vector_analysis_indices |
| ORDER BY table_name, index_name; |
| """) |
| found_indexes = set(cur.fetchall()) |
|
|
| |
| missing_indexes = actual_vector_indexes - found_indexes |
| if missing_indexes: |
| results['issues'].append(f"Agent missed vector indexes: {missing_indexes}") |
|
|
| |
| |
|
|
| if not missing and not extra and count > 0 and not missing_indexes: |
| results['passed'] = True |
|
|
| except psycopg2.Error as e: |
| results['issues'].append(f"Database error: {e}") |
| except Exception as e: |
| results['issues'].append(f"Verification error: {e}") |
| return results |
|
|
|
|
| def verify_no_extra_analysis_tables(conn) -> Dict[str, Any]: |
| """Check that only the required analysis tables exist (no legacy/extra analysis tables).""" |
| results = {'passed': True, 'issues': []} |
| required = { |
| 'vector_analysis_columns', |
| 'vector_analysis_storage_consumption', |
| 'vector_analysis_indices', |
| } |
| try: |
| with conn.cursor() as cur: |
| cur.execute(""" |
| SELECT table_name FROM information_schema.tables |
| WHERE table_schema = 'public' |
| AND table_name LIKE 'vector_analysis_%'; |
| """) |
| analysis_tables = {row[0] for row in cur.fetchall()} |
|
|
| |
| |
| analysis_tables_filtered = {t for t in analysis_tables if not t.startswith('expected_') and not t.startswith('vector_analysis_results')} |
| extra = analysis_tables_filtered - required |
| if extra: |
| results['issues'].append(f"Found unexpected analysis tables: {extra}") |
| results['passed'] = False |
|
|
| except Exception as e: |
| results['issues'].append(f"Verification error: {e}") |
| results['passed'] = False |
| return results |
|
|
|
|
|
|
| def main(): |
| """Main verification function for vector analysis deliverables.""" |
|
|
| conn_params = get_connection_params() |
| if not conn_params["database"]: |
| print("No database specified") |
| sys.exit(1) |
| try: |
| conn = psycopg2.connect(**conn_params) |
| checks = [ |
| ("vector_analysis_columns", verify_vector_analysis_columns), |
| ("vector_analysis_storage_consumption", verify_vector_analysis_storage_consumption), |
| ("vector_analysis_indices", verify_vector_analysis_indices), |
| ("no_extra_analysis_tables", verify_no_extra_analysis_tables), |
| ] |
| passed_checks = 0 |
| all_issues = [] |
| for i, (desc, check_func) in enumerate(checks, 1): |
| result = check_func(conn) |
| if result['passed']: |
| print(f" PASSED") |
| passed_checks += 1 |
| else: |
| print(f" FAILED") |
| for issue in result['issues']: |
| print(f" - {issue}") |
| all_issues.extend(result['issues']) |
| print() |
| conn.close() |
| total_checks = len(checks) |
| print(f"Results: {passed_checks}/{total_checks} checks passed") |
| if passed_checks == total_checks: |
| sys.exit(0) |
| elif passed_checks >= total_checks * 0.75: |
| sys.exit(0) |
| else: |
| sys.exit(1) |
| except psycopg2.Error as e: |
| print(f"Database connection error: {e}") |
| sys.exit(1) |
| except Exception as e: |
| print(f"Verification error: {e}") |
| sys.exit(1) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|