
    $j5                     6    d Z ddlmZmZ  G d de          ZdS )zAbstract base class for SQL dialect modules.

Each method encapsulates a SQL pattern that differs between database platforms.
Business logic calls these methods instead of embedding raw SQL fragments.
    )ABCabstractmethodc                      e Zd ZdZededefd            Zedededefd            Zedededefd	            Z	edededefd
            Z
edededefd            Zedededefd            Zedededefd            Zedddedededz  defd            Zedddedededz  defd            Zedededefd            Zededee         dee         dee         def
d            Zedeeeef                  defd            Zedededefd            Zedee         defd             Zedededefd!            Zededefd"            Zededefd#            Zedededefd$            Zedefd%            Zed&edefd'            Zedefd(            Zed)edefd*            Zedefd+            Zed,edefd-            Z ed.d.d.d/ded0ed1ed2ed3ed4ed5ed6ed7edefd8            Z!ed.d.d9d:d.d;ded0ed1ed3eded<ed5ed6ed=ed>ed7edefd?            Z"ed:d@dAee         dBed>edefdC            Z#dS )D
SQLDialecta  SQL dialect interface for portable query construction.

    Implementors provide database-specific SQL fragments for operations that
    are not standard across PostgreSQL and Oracle (parameter binding, JSON
    operators, vector distance, full-text search, etc.).
    nreturnc                     dS )zReturn the nth positional parameter placeholder.

        Args:
            n: 1-based parameter index.

        Returns:
            "$1" for PostgreSQL, ":1" for Oracle.
        N )selfr   s     e/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/hindsight_api/engine/sql/base.pyparamzSQLDialect.param   	     	    r   	type_namec                     dS )a?  Cast a parameter or expression to the given type.

        Args:
            param: The expression to cast (e.g. "$1" or a column name).
            type_name: Target type (e.g. "jsonb", "uuid[]", "vector").

        Returns:
            Cast expression (e.g. "$1::jsonb" for PG, "CAST(:1 AS ...)" for Oracle).
        Nr
   )r   r   r   s      r   castzSQLDialect.cast"   	     	r   colc                     dS )am  Cosine distance expression between a column and a parameter.

        Args:
            col: Column name containing the vector.
            param: Parameter placeholder for the query vector.

        Returns:
            Distance expression (lower = more similar).
            PG: "col <=> $1::vector"
            Oracle: "VECTOR_DISTANCE(col, :1, COSINE)"
        Nr
   r   r   r   s      r   vector_distancezSQLDialect.vector_distance1   s	     	r   c                     dS )zCosine similarity expression (1 - distance).

        Args:
            col: Column name.
            param: Parameter placeholder.

        Returns:
            Similarity expression (higher = more similar).
        Nr
   r   s      r   vector_similarityzSQLDialect.vector_similarity@   r   r   keyc                     dS )zExtract a text value from a JSON/JSONB column.

        Args:
            col: Column name.
            key: JSON key to extract.

        Returns:
            PG: "col ->> 'key'"
            Oracle: "JSON_VALUE(col, '$.key')"
        Nr
   )r   r   r   s      r   json_extract_textzSQLDialect.json_extract_textO   	     	r   c                     dS )a  Test whether a JSON column contains the given JSON object.

        Args:
            col: Column name.
            param: Parameter placeholder for the JSON object to test.

        Returns:
            PG: "col @> $1::jsonb"
            Oracle: "JSON_EXISTS(col, ...)"
        Nr
   r   s      r   json_containszSQLDialect.json_contains]   r   r   c                     dS )a  Merge (concatenate) a JSON object into a JSON column.

        Args:
            col: Column name.
            param: Parameter placeholder for the JSON to merge.

        Returns:
            PG: "col || $1::jsonb"
            Oracle: "JSON_MERGEPATCH(col, :1)"
        Nr
   r   s      r   
json_mergezSQLDialect.json_mergek   r   r   N)
index_namequery_paramr"   c                    dS )aY  Relevance score expression for full-text search.

        Args:
            col: Column name (text or tsvector/bm25vector).
            query_param: Parameter placeholder for the search query.
            index_name: Optional index name (needed by some backends).

        Returns:
            Score expression (higher = more relevant).
        Nr
   r   r   r#   r"   s       r   text_search_scorezSQLDialect.text_search_score{   r   r   c                    dS )a2  ORDER BY expression for full-text search (ascending = best first).

        Args:
            col: Column name.
            query_param: Parameter placeholder for the search query.
            index_name: Optional index name.

        Returns:
            Expression suitable for ORDER BY ... ASC.
        Nr
   r%   s       r   text_search_orderzSQLDialect.text_search_order   r   r   c                     dS )a!  Fuzzy string similarity score between a column and a parameter.

        Args:
            col: Column name.
            param: Parameter placeholder.

        Returns:
            PG: "similarity(col, $1)"
            Oracle: "UTL_MATCH.EDIT_DISTANCE_SIMILARITY(col, :1) / 100.0"
        Nr
   r   s      r   
similarityzSQLDialect.similarity   r   r   tablecolumnsconflict_columnsupdate_columnsc                     dS )a  Generate an upsert statement.

        Args:
            table: Fully-qualified table name.
            columns: All columns in the INSERT.
            conflict_columns: Columns that form the unique constraint.
            update_columns: Columns to update on conflict.

        Returns:
            Complete INSERT ... ON CONFLICT DO UPDATE (PG)
            or MERGE INTO ... (Oracle) statement.
        Nr
   )r   r+   r,   r-   r.   s        r   upsertzSQLDialect.upsert   s	    ( 	r   param_typesc                     dS )ao  Generate a bulk unnest/table-value expression.

        Converts parallel arrays into rows.

        Args:
            param_types: List of (param_placeholder, sql_type) pairs
                         e.g. [("$1", "text[]"), ("$2", "uuid[]")]

        Returns:
            PG: "unnest($1::text[], $2::uuid[])"
            Oracle: JSON_TABLE-based equivalent.
        Nr
   )r   r1   s     r   bulk_unnestzSQLDialect.bulk_unnest   s	     	r   limit_paramoffset_paramc                     dS )a(  Generate LIMIT/OFFSET clause.

        Args:
            limit_param: Parameter placeholder for row limit.
            offset_param: Parameter placeholder for row offset.

        Returns:
            PG: "LIMIT $1 OFFSET $2"
            Oracle: "OFFSET :2 ROWS FETCH FIRST :1 ROWS ONLY"
        Nr
   )r   r4   r5   s      r   limit_offsetzSQLDialect.limit_offset   r   r   c                     dS )zGenerate a RETURNING clause.

        Args:
            columns: Column names to return.

        Returns:
            PG: "RETURNING col1, col2"
            Oracle: "RETURNING col1, col2 INTO :out1, :out2" (handled by backend).
        Nr
   )r   r,   s     r   	returningzSQLDialect.returning   r   r   c                     dS )zCase-insensitive LIKE expression.

        Args:
            col: Column name.
            param: Parameter placeholder for the pattern.

        Returns:
            PG: "col ILIKE $1"
            Oracle: "UPPER(col) LIKE UPPER(:1)"
        Nr
   r   s      r   ilikezSQLDialect.ilike   r   r   c                     dS )zIN-array membership expression.

        Args:
            param: Parameter placeholder for the array.

        Returns:
            PG: "= ANY($1)"
            Oracle: "IN (SELECT ... FROM JSON_TABLE(...))"
        Nr
   r   r   s     r   	array_anyzSQLDialect.array_any  r   r   c                     dS )zNOT-IN-array expression (not equal to all elements).

        Args:
            param: Parameter placeholder for the array.

        Returns:
            PG: "!= ALL($1)"
        Nr
   r=   s     r   	array_allzSQLDialect.array_all  r   r   c                     dS )zTest whether an array column contains all elements in the parameter.

        Args:
            col: Array column name.
            param: Parameter placeholder for the array to test.

        Returns:
            PG: "col @> $1::varchar[]"
        Nr
   r   s      r   array_containszSQLDialect.array_contains  r   r   c                     dS )z;FOR UPDATE SKIP LOCKED clause (same on both PG and Oracle).Nr
   r   s    r   for_update_skip_lockedz!SQLDialect.for_update_skip_locked*  	     	r   id_paramc                     dS )zAdvisory lock expression.

        Args:
            id_param: Parameter placeholder for the lock ID.

        Returns:
            PG: "pg_try_advisory_lock($1)"
            Oracle: "SELECT ... FOR UPDATE NOWAIT" equivalent.
        Nr
   )r   rG   s     r   advisory_lockzSQLDialect.advisory_lock/  r   r   c                     dS )zSQL expression to generate a random UUID.

        Returns:
            PG: "gen_random_uuid()"
            Oracle: "SYS_GUID()"
        Nr
   rD   s    r   generate_uuidzSQLDialect.generate_uuid>  	     	r   argsc                     dS )z-GREATEST() function (same on both platforms).Nr
   )r   rM   s     r   greatestzSQLDialect.greatestJ  rF   r   c                     dS )zsCurrent timestamp expression.

        Returns:
            PG: "now()"
            Oracle: "SYSTIMESTAMP"
        Nr
   rD   s    r   current_timestampzSQLDialect.current_timestampO  rL   r   exprc                     dS )zAggregate values into an array.

        Args:
            expr: Expression to aggregate.

        Returns:
            PG: "array_agg(expr)"
            Oracle: "CAST(COLLECT(expr) AS ...)" or JSON_ARRAYAGG.
        Nr
   )r   rR   s     r   	array_aggzSQLDialect.array_aggY  r   r    )tags_clausegroups_clauseextra_wherecols	fact_typeembedding_parambank_id_paramfetch_limitrV   rW   rX   c       	             dS )aA  Build a semantic (vector similarity) search subquery arm.

        Returns a complete subquery suitable for UNION ALL that selects
        matching rows ordered by cosine similarity.

        Args:
            table: Fully-qualified table name.
            cols: Column list expression.
            fact_type: Fact type literal (inlined, not parameterized).
            embedding_param: Parameter placeholder for query embedding.
            bank_id_param: Parameter placeholder for bank_id.
            fetch_limit: Max rows to fetch (over-fetched for HNSW approximation).
            tags_clause: Optional WHERE clause fragment for tag filtering.
            groups_clause: Optional WHERE clause fragment for tag group filtering.
            extra_where: Optional additional WHERE clause fragment (e.g. time range filter).
        Nr
   )
r   r+   rY   rZ   r[   r\   r]   rV   rW   rX   s
             r   build_semantic_armzSQLDialect.build_semantic_arml  s	    < 	r   r   native)rV   rW   	arm_indextext_search_extensionrX   
text_paramra   rb   c                    dS )a?  Build a BM25/full-text search subquery arm.

        Returns a complete subquery suitable for UNION ALL that selects
        matching rows ordered by text relevance score.

        Args:
            table: Fully-qualified table name.
            cols: Column list expression.
            fact_type: Fact type literal (inlined, not parameterized).
            bank_id_param: Parameter placeholder for bank_id.
            limit_param: Parameter placeholder for result limit.
            text_param: Parameter placeholder for the search text.
            tags_clause: Optional WHERE clause fragment for tag filtering.
            groups_clause: Optional WHERE clause fragment for tag group filtering.
            arm_index: Index of this arm in the UNION ALL (used by Oracle for
                       unique SCORE labels).
            text_search_extension: Full-text search backend ("native", "vchord",
                                   "pg_textsearch"). Only relevant for PostgreSQL.
            extra_where: Optional additional WHERE clause fragment (e.g. time range filter).
        Nr
   )r   r+   rY   rZ   r\   r4   rc   rV   rW   ra   rb   rX   s               r   build_bm25_armzSQLDialect.build_bm25_arm  s
    H 	r   )rb   tokens
query_textc                    dS )a  Prepare the text parameter value for BM25 search.

        Transforms tokens/query text into the format expected by the backend's
        full-text search engine.

        Args:
            tokens: Tokenized query words.
            query_text: Original query text.
            text_search_extension: Full-text search backend variant.

        Returns:
            Prepared text string to bind as the BM25 text parameter.
        Nr
   )r   rf   rg   rb   s       r   prepare_bm25_textzSQLDialect.prepare_bm25_text  s	    * 	r   )$__name__
__module____qualname____doc__r   intstrr   r   r   r   r   r   r!   r&   r(   r*   listr0   tupler3   r7   r9   r;   r>   r@   rB   rE   rI   rK   rO   rQ   rT   r_   re   ri   r
   r   r   r   r   
   s         	s 	s 	 	 	 ^	 
# 
# 
# 
 
 
 ^
 3 s s    ^ 
S 
 
 
 
 
 ^
 S s s    ^  S S    ^ c # #    ^ X\   S s 3QU: ad    ^ X\   S s 3QU: ad    ^ c # #    ^  c s)	
 S	 
   ^. tE#s(O'<     ^"  3 3    ^ 
c 
s 
 
 
 ^
  S S    ^ 
s 
s 
 
 
 ^
 	s 	s 	 	 	 ^	 
# 
c 
c 
 
 
 ^
     ^ 
c 
c 
 
 
 ^
 s    ^ c c    ^ 3    ^ 
c 
c 
 
 
 ^
$      	
        
   ^>  %-# # # # 	#
 # # # # # # #  ## # 
# # # ^#J  &.  S	 
  # 
   ^  r   r   N)rm   abcr   r   r   r
   r   r   <module>rs      sg     $ # # # # # # #} } } } } } } } } }r   