#!/usr/bin/env python3 """ カラム名検証スクリプト PostgreSQLで問題となるカラム名を事前にチェック """ import os import psycopg2 import logging # ログ設定 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # データベース設定 ROGDB_CONFIG = { 'host': os.getenv('ROGDB_HOST', 'postgres-db'), 'database': os.getenv('ROGDB_NAME', 'rogdb'), 'user': os.getenv('ROGDB_USER', 'admin'), 'password': os.getenv('ROGDB_PASSWORD', 'admin123456'), 'port': int(os.getenv('ROGDB_PORT', 5432)) } # PostgreSQL予約語 RESERVED_KEYWORDS = { 'like', 'order', 'group', 'user', 'table', 'where', 'select', 'insert', 'update', 'delete', 'create', 'drop', 'alter', 'index', 'constraint', 'default', 'check', 'unique', 'primary', 'foreign', 'key', 'references' } def check_column_names(): """全rog_テーブルのカラム名をチェック""" try: conn = psycopg2.connect(**ROGDB_CONFIG) cursor = conn.cursor() # rog_テーブル一覧取得 cursor.execute(""" SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name LIKE 'rog_%' ORDER BY table_name """) tables = [row[0] for row in cursor.fetchall()] logger.info(f"チェック対象テーブル: {len(tables)}個") problematic_columns = {} for table_name in tables: # テーブルのカラム一覧取得 cursor.execute(""" SELECT column_name FROM information_schema.columns WHERE table_name = %s AND table_schema = 'public' ORDER BY ordinal_position """, (table_name,)) columns = [row[0] for row in cursor.fetchall()] problem_cols = [] for col in columns: # 予約語チェック if col.lower() in RESERVED_KEYWORDS: problem_cols.append((col, '予約語')) # キャメルケース/大文字チェック elif any(c.isupper() for c in col) or col != col.lower(): problem_cols.append((col, 'キャメルケース/大文字')) if problem_cols: problematic_columns[table_name] = problem_cols # 結果出力 if problematic_columns: logger.warning("⚠️ 問題のあるカラム名が見つかりました:") for table, cols in problematic_columns.items(): logger.warning(f" {table}:") for col, reason in cols: logger.warning(f" - {col} ({reason})") else: logger.info("✅ 全てのカラム名は問題ありません") # クォートが必要なカラムのリスト生成 need_quotes = set() for table, cols in problematic_columns.items(): for col, reason in cols: need_quotes.add(col) if need_quotes: logger.info("📋 クォートが必要なカラム一覧:") for col in sorted(need_quotes): logger.info(f" '{col}' -> '\"{col}\"'") cursor.close() conn.close() return problematic_columns except Exception as e: logger.error(f"❌ カラム名チェックエラー: {e}") return {} def test_quoted_query(): """クォート付きクエリのテスト""" try: conn = psycopg2.connect(**ROGDB_CONFIG) cursor = conn.cursor() # 問題のあるテーブルでテストクエリ実行 test_tables = ['rog_entry', 'rog_newevent2'] for table_name in test_tables: logger.info(f"=== {table_name} クエリテスト ===") # カラム一覧取得 cursor.execute(""" SELECT column_name FROM information_schema.columns WHERE table_name = %s AND table_schema = 'public' ORDER BY ordinal_position """, (table_name,)) columns = [row[0] for row in cursor.fetchall()] # クォート付きカラム名生成 def quote_column_if_needed(column_name): if column_name.lower() in RESERVED_KEYWORDS: return f'"{column_name}"' if any(c.isupper() for c in column_name) or column_name != column_name.lower(): return f'"{column_name}"' return column_name quoted_columns = [quote_column_if_needed(col) for col in columns] columns_str = ', '.join(quoted_columns) # テストクエリ実行 try: test_query = f"SELECT {columns_str} FROM {table_name} LIMIT 1" logger.info(f"テストクエリ: {test_query[:100]}...") cursor.execute(test_query) result = cursor.fetchone() logger.info(f"✅ {table_name}: クエリ成功") except Exception as e: logger.error(f"❌ {table_name}: クエリエラー: {e}") cursor.close() conn.close() except Exception as e: logger.error(f"❌ クエリテストエラー: {e}") def main(): logger.info("=" * 60) logger.info("PostgreSQL カラム名検証スクリプト") logger.info("=" * 60) # カラム名チェック problematic_columns = check_column_names() print() # クエリテスト test_quoted_query() logger.info("=" * 60) logger.info("検証完了") logger.info("=" * 60) if __name__ == "__main__": main()