
    Ki&              	         U d Z ddlmZ ddlZddlZddlmZ  ej                  e      Z	ddZ
ddZ eh d      ZddZdd	Zdd
ZddZddZddZddZddZddZddZeeeeeeeedZded<    eej7                               ZddZy)zSchema migration framework for the code-review-graph SQLite database.

Manages incremental schema changes via versioned migration functions.
Each migration is idempotent (uses IF NOT EXISTS / column existence checks).
    )annotationsN)Callablec                    	 | j                  d      j                         }|yt        t        |t        t
        f      r	|d         S |d         S # t        j                  $ r Y yw xY w)zRead the current schema version from the metadata table.

    Returns:
        int: The schema version (0 if metadata table doesn't exist, 1 if not set).
    z7SELECT value FROM metadata WHERE key = 'schema_version'   r   value)executefetchoneint
isinstancetuplelistsqlite3OperationalError)connrows     h/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/code_review_graph/migrations.pyget_schema_versionr      sl    	llE

(* 	 ;ZeT];3q6NNWNN## s   !A #A A A'&A'c                <    | j                  dt        |      f       y)z-Set the schema version in the metadata table.zIINSERT OR REPLACE INTO metadata (key, value) VALUES ('schema_version', ?)N)r   str)r   versions     r   _set_schema_versionr   "   s    LLS	W    >
   edgesflowsnodesmetadata	nodes_fts
risk_indexcommunitiesflow_snapshotsflow_membershipscommunity_summariesc                    |t         vrt        d|       | j                  d| d      }|D cg c]  }t        |t              r|d   n|d    }}||v S c c}w )z$Check if a column exists in a table.Unknown table: zPRAGMA table_info()r   name)_KNOWN_TABLES
ValueErrorr   r   r   )r   tablecolumncursorr   columnss         r   _has_columnr-   0   sn    M!?5'233\\.ugQ78FLRSSC/s1vS[@SGSW Ts   !Ac                    |t         vrt        d|       | j                  d|f      j                         }|d   dkD  S )zCheck if a table exists.r$   zOSELECT count(*) FROM sqlite_master WHERE type IN ('table', 'view') AND name = ?r   )r'   r(   r   r	   )r   r)   r   s      r   _table_existsr/   9   sP    M!?5'233
,,		 hj	 
 q6A:r   c                l    t        | dd      s'| j                  d       t        j                  d       yy)z(v2: Add signature column to nodes table.r   	signaturez+ALTER TABLE nodes ADD COLUMN signature TEXTz/Migration v2: added 'signature' column to nodesNr-   r   loggerinfor   s    r   _migrate_v2r6   J   s-    tWk2BCEF 3r   c                    | j                  d       | j                  d       | j                  d       | j                  d       | j                  d       t        j                  d       y)z-v3: Create flows and flow_memberships tables.a  
        CREATE TABLE IF NOT EXISTS flows (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            entry_point_id INTEGER NOT NULL,
            depth INTEGER NOT NULL,
            node_count INTEGER NOT NULL,
            file_count INTEGER NOT NULL,
            criticality REAL NOT NULL DEFAULT 0.0,
            path_json TEXT NOT NULL,
            created_at TEXT NOT NULL DEFAULT (datetime('now')),
            updated_at TEXT NOT NULL DEFAULT (datetime('now'))
        )
    z
        CREATE TABLE IF NOT EXISTS flow_memberships (
            flow_id INTEGER NOT NULL,
            node_id INTEGER NOT NULL,
            position INTEGER NOT NULL,
            PRIMARY KEY (flow_id, node_id)
        )
    zKCREATE INDEX IF NOT EXISTS idx_flows_criticality ON flows(criticality DESC)zCCREATE INDEX IF NOT EXISTS idx_flows_entry ON flows(entry_point_id)zQCREATE INDEX IF NOT EXISTS idx_flow_memberships_node ON flow_memberships(node_id)z7Migration v3: created flows and flow_memberships tablesNr   r3   r4   r5   s    r   _migrate_v3r9   Q   sh    LL  	 	LL  	 	LLU 	LLM 	LL[ KKIJr   c                   | j                  d       t        | dd      s&| j                  d       t        j                  d       | j                  d       | j                  d       | j                  d       t        j                  d	       y
)z8v4: Create communities table, add community_id to nodes.a  
        CREATE TABLE IF NOT EXISTS communities (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            level INTEGER NOT NULL DEFAULT 0,
            parent_id INTEGER,
            cohesion REAL NOT NULL DEFAULT 0.0,
            size INTEGER NOT NULL DEFAULT 0,
            dominant_language TEXT,
            description TEXT,
            created_at TEXT NOT NULL DEFAULT (datetime('now'))
        )
    r   community_idz1ALTER TABLE nodes ADD COLUMN community_id INTEGERz2Migration v4: added 'community_id' column to nodeszECREATE INDEX IF NOT EXISTS idx_nodes_community ON nodes(community_id)zKCREATE INDEX IF NOT EXISTS idx_communities_parent ON communities(parent_id)zQCREATE INDEX IF NOT EXISTS idx_communities_cohesion ON communities(cohesion DESC)z'Migration v4: created communities tableN)r   r-   r3   r4   r5   s    r   _migrate_v4r<   u   s{    LL  	 tWn5HIHILLO 	LLU 	LL[ KK9:r   c                j    t        | d      s'| j                  d       t        j                  d       yy)z(v5: Create FTS5 virtual table for nodes.r   z
            CREATE VIRTUAL TABLE nodes_fts USING fts5(
                name, qualified_name, file_path, signature,
                content='nodes', content_rowid='rowid',
                tokenize='porter unicode61'
            )
        z2Migration v5: created nodes_fts FTS5 virtual tableN)r/   r   r3   r4   r5   s    r   _migrate_v5r>      s1    {+  	 	HI ,r   c                    | j                  d       | j                  d       | j                  d       | j                  d       t        j                  d       y)z@v6: Add pre-computed summary tables for token-efficient queries.a  
        CREATE TABLE IF NOT EXISTS community_summaries (
            community_id INTEGER PRIMARY KEY,
            name TEXT NOT NULL,
            purpose TEXT DEFAULT '',
            key_symbols TEXT DEFAULT '[]',
            risk TEXT DEFAULT 'unknown',
            size INTEGER DEFAULT 0,
            dominant_language TEXT DEFAULT '',
            FOREIGN KEY (community_id) REFERENCES communities(id)
        )
    a  
        CREATE TABLE IF NOT EXISTS flow_snapshots (
            flow_id INTEGER PRIMARY KEY,
            name TEXT NOT NULL,
            entry_point TEXT NOT NULL,
            critical_path TEXT DEFAULT '[]',
            criticality REAL DEFAULT 0.0,
            node_count INTEGER DEFAULT 0,
            file_count INTEGER DEFAULT 0,
            FOREIGN KEY (flow_id) REFERENCES flows(id)
        )
    a  
        CREATE TABLE IF NOT EXISTS risk_index (
            node_id INTEGER PRIMARY KEY,
            qualified_name TEXT NOT NULL,
            risk_score REAL DEFAULT 0.0,
            caller_count INTEGER DEFAULT 0,
            test_coverage TEXT DEFAULT 'unknown',
            security_relevant INTEGER DEFAULT 0,
            last_computed TEXT DEFAULT '',
            FOREIGN KEY (node_id) REFERENCES nodes(id)
        )
    zNCREATE INDEX IF NOT EXISTS idx_risk_index_score ON risk_index(risk_score DESC)zVMigration v6: created summary tables (community_summaries, flow_snapshots, risk_index)Nr8   r5   s    r   _migrate_v6r@      sa    LL  	 	LL  	 	LL  	 	LL	) KK D Er   c                r    | j                  d       | j                  d       t        j                  d       y)z;v7: Add compound edge indexes for summary and risk queries.zQCREATE INDEX IF NOT EXISTS idx_edges_target_kind ON edges(target_qualified, kind)zQCREATE INDEX IF NOT EXISTS idx_edges_source_kind ON edges(source_qualified, kind)z)Migration v7: added compound edge indexesNr8   r5   s    r   _migrate_v7rB      s5    LL	+ 	LL	+ KK;<r   c                P    | j                  d       t        j                  d       y)z=v8: Add composite index on edges for upsert_edge performance.z
        CREATE INDEX IF NOT EXISTS idx_edges_composite
        ON edges(kind, source_qualified, target_qualified, file_path, line)
    z*Migration v8: created composite edge indexNr8   r5   s    r   _migrate_v8rD      s"    LL  	 KK<=r   c                    t        | dd      s| j                  d       t        | dd      s| j                  d       t        j                  d       y)z$v9: Add confidence scoring to edges.r   
confidencez8ALTER TABLE edges ADD COLUMN confidence REAL DEFAULT 1.0confidence_tierzEALTER TABLE edges ADD COLUMN confidence_tier TEXT DEFAULT 'EXTRACTED'z+Migration v9: added edge confidence columnsNr2   r5   s    r   _migrate_v9rH      sJ    tWl3F	
 tW&78S	
 KK=>r   )                     	   z/dict[int, Callable[[sqlite3.Connection], None]]
MIGRATIONSc                   t        |       }|t        k\  ryt        j                  d|t               t	        t
        j                               D ]I  }||k  r	t        j                  d|       	 t        |   |        t        | |       | j                          K t        j                  dt               y# t        j                  $ r* | j                          t        j                  d|d        w xY w)zRun all pending migrations in order.

    Each migration runs in its own transaction. The schema_version metadata
    entry is updated after each successful migration.
    Nz+Schema version %d -> %d: running migrationszRunning migration v%dz"Migration v%d failed, rolling backT)exc_infoz-Migrations complete, now at schema version %d)r   LATEST_VERSIONr3   r4   sortedrQ   keysr   commitr   Errorrollbackerror)r   currentr   s      r   run_migrationsr\     s     !&G. 
KK=wW*//+, g+W5	w%g.KKM KK?P }} 	MMOLL=wQULV	s   .*B55=C2)r   sqlite3.Connectionreturnr
   )r   r]   r   r
   r^   None)r   r]   r)   r   r*   r   r^   bool)r   r]   r)   r   r^   r`   )r   r]   r^   r_   )__doc__
__future__r   loggingr   typingr   	getLogger__name__r3   r   r   	frozensetr'   r-   r/   r6   r9   r<   r>   r@   rB   rD   rH   rQ   __annotations__maxrV   rT   r\    r   r   <module>rk      s    #   			8	$$   	"G!KH;<
J+E\
=>
?$ 	?
; 	 Z__&'Qr   