
    B>qjs                        d dl Z d dlZd dl d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lm	Z	 d d
lm
Z
 d dlmZ d dlmZ dZdZdZdZ G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d d e      Z G d! d"e      Z G d# d$e       Z! G d% d&e"      Z# G d' d(e$      Z% G d) d*e%      Z& G d+ d,e&      Z'd-Z( e)d.       e)e(      z   e)e(jU                               z   e) e+d/      f      z  Z, e)d0  e-d1      D              Z.[([, ej^                  d2      Z0 G d3 d4e&      Z1d5e	_2        d6 Z3y)7    N)*)
ColumnBase)EnclosedNodeList)Entity)
Expression)Node)NodeList)OP)
merge_dict)sqlite3)
fts_parserpcxpcnalx   )   	   r   c                   .     e Zd ZdZdxZxZZ fdZ xZS )
RowIDFieldTrowidc                     || j                   k7  r$t        t        |       d| j                   d      t        t        |   ||g|  y )Nz must be named "z".)required_name
ValueErrortypesuperr   bind)selfmodelnameargs	__class__s       S/opt/rentech/trading_bot/.venv/lib/python3.12/site-packages/playhouse/sqlite_ext.pyr   zRowIDField.bind   sH    4%%%"4j$*<*<> ? ?j$$UD848    )	__name__
__module____qualname__auto_incrementcolumn_namer   r   r   __classcell__r    s   @r!   r   r      s!    N)00K0$9 9r"   r   c                       e Zd ZdxZxZZy)
DocIDFielddocidN)r#   r$   r%   r'   r   r    r"   r!   r+   r+   "   s    )00K0$r"   r+   c                        e Zd Z fdZ xZS )AutoIncrementFieldc                 V    t         t        |   |      }t        |t	        d      f      S )NAUTOINCREMENT)r   r/   ddlr	   SQL)r   ctx	node_listr    s      r!   r2   zAutoIncrementField.ddl'   s*    ,d7<	C$89::r"   )r#   r$   r%   r2   r(   r)   s   @r!   r/   r/   &   s    ; ;r"   r/   c                       e Zd ZdZd Zy)TDecimalFieldTEXTc                      y Nr-   r   s    r!   get_modifierszTDecimalField.get_modifiers.   s    r"   N)r#   r$   r%   
field_typer<   r-   r"   r!   r7   r7   ,   s
    J!r"   r7   c                       e Zd Zg dZd Zy)ISODateTimeField)z%Y-%m-%dT%H:%M:%S.%f%zz%Y-%m-%dT%H:%M:%S%zz%Y-%m-%dT%H:%M:%S.%fz%Y-%m-%dT%H:%M:%Sz%Y-%m-%dc                     t        |t              r| j                  |      }|r t        |t              s|j                         S |S r:   )
isinstancestradapt	isoformatr   values     r!   db_valuezISODateTimeField.db_value:   s8    eS!JJu%EE3/??$$r"   N)r#   r$   r%   formatsrG   r-   r"   r!   r?   r?   1   s    Gr"   r?   c                        e Zd Zd fd	Zd Zed        Zd ZddZddZ	ddZ
ddZdd	Zd
 Zd Zd Zd Zd Zd Zd Z xZS )JSONPathc                 N    t         t        |           || _        |xs d| _        y Nr-   )r   rJ   __init___field_path)r   fieldpathr    s      r!   rM   zJSONPath.__init__D   s"    h&(ZR
r"   c                 8    | j                   j                  |      S r:   )rN   python_valuerE   s     r!   
_converterzJSONPath._converterI   s    {{''..r"   c                 P    t        ddj                  | j                        z        S )Nz$%s )ValuejoinrO   r;   s    r!   rQ   zJSONPath.pathL   s    URWWTZZ0011r"   c                     t        |t              s|dk(  rd|z  }nd|j                  dd      z  } t        |       | j                  | j
                  |fz         S )N#z[%s]z."%s""z"")rA   intreplacer   rN   rO   )r   idxitems      r!   __getitem__zJSONPath.__getitem__P   sR    c33#:C<DS[[d33DtDz$++tzzTG';<<r"   c                     |st        |t        t        f      r.t        j	                  | j
                  j                  |            }t        j                  | j
                  | d   j                  |      S NrZ   )	rA   listdictfnjsonrN   _json_dumpsjson_setrQ   r   rF   as_jsons      r!   appendzJSONPath.appendW   sN    jt5GGDKK33E:;E{{4;;S	>>r"   c                     |st        |t        t        f      r.t        j	                  | j
                  j                  |            } || j
                  | j                  |      S r:   )rA   rc   rd   re   rf   rN   rg   rQ   r   funcrF   rj   s       r!   _json_operationzJSONPath._json_operation\   sF    jt5GGDKK33E:;EDKKE22r"   c                 D    | j                  t        j                  ||      S r:   )ro   re   json_insertri   s      r!   insertzJSONPath.inserta   s    ##BNNE7CCr"   c                 D    | j                  t        j                  ||      S r:   )ro   re   rh   ri   s      r!   setzJSONPath.setd   s    ##BKK@@r"   c                 D    | j                  t        j                  ||      S r:   )ro   re   json_replaceri   s      r!   r]   zJSONPath.replaceg       ##BOOUGDDr"   c                 ~    | j                  t        j                  | | j                  j	                  |                  S r:   )rt   re   
json_patchrN   rg   rE   s     r!   updatezJSONPath.updatej   s+    xxdDKK,C,CE,JKLLr"   c                 V    t         j                  | j                  | j                        S r:   )re   json_removerN   rQ   r;   s    r!   removezJSONPath.removem   s    ~~dkk49955r"   c                 V    t         j                  | j                  | j                        S r:   )re   	json_typerN   rQ   r;   s    r!   r   zJSONPath.json_typep       ||DKK33r"   c                 V    t         j                  | j                  | j                        S r:   )re   json_array_lengthrN   rQ   r;   s    r!   lengthzJSONPath.lengths   s    ##DKK;;r"   c                 V    t         j                  | j                  | j                        S r:   )re   	json_eachrN   rQ   r;   s    r!   childrenzJSONPath.childrenv   r   r"   c                 V    t         j                  | j                  | j                        S r:   )re   	json_treerN   rQ   r;   s    r!   treezJSONPath.treey   r   r"   c                     |j                  | j                  r.t        j                  | j                  | j
                              S | j                        S r:   )sqlrO   re   json_extractrN   rQ   r   r4   s     r!   __sql__zJSONPath.__sql__|   sC    ww** t{{DII> 7 	7*.++7 	7r"   r:   )r#   r$   r%   rM   rT   propertyrQ   r`   rk   ro   rr   rt   r]   rz   r}   r   r   r   r   r   r(   r)   s   @r!   rJ   rJ   C   sf     
/ 2 2=?
3
DAEM64<447r"   rJ   c                   F    e Zd Zd
dZd
dZd
dZd
dZd
dZd Zd Z	d	 Z
y)	JSONBPathNc                     |st        |t        t        f      r.t        j	                  | j
                  j                  |            }t        j                  | j
                  | d   j                  |      S rb   )	rA   rc   rd   re   jsonbrN   rg   	jsonb_setrQ   ri   s      r!   rk   zJSONBPath.append   sN    jt5HHT[[44U;<E||DKKc??r"   c                     |st        |t        t        f      r.t        j	                  | j
                  j                  |            } || j
                  | j                  |      S r:   )rA   rc   rd   re   r   rN   rg   rQ   rm   s       r!   ro   zJSONBPath._json_operation   sF    jt5HHT[[44U;<EDKKE22r"   c                 D    | j                  t        j                  ||      S r:   )ro   re   jsonb_insertri   s      r!   rr   zJSONBPath.insert   rw   r"   c                 D    | j                  t        j                  ||      S r:   )ro   re   r   ri   s      r!   rt   zJSONBPath.set   s    ##BLL%AAr"   c                 D    | j                  t        j                  ||      S r:   )ro   re   jsonb_replaceri   s      r!   r]   zJSONBPath.replace   s    ##B$4$4eWEEr"   c                 ~    | j                  t        j                  | | j                  j	                  |                  S r:   )rt   re   jsonb_patchrN   rg   rE   s     r!   rz   zJSONBPath.update   s+    xxtT[[-D-DU-KLMMr"   c                 V    t         j                  | j                  | j                        S r:   )re   jsonb_removerN   rQ   r;   s    r!   r}   zJSONBPath.remove   s    t{{DII66r"   c                     |j                  | j                  r.t        j                  | j                  | j
                              S | j                        S r:   )r   rO   re   jsonb_extractrN   rQ   r   s     r!   r   zJSONBPath.__sql__   sE    ww** ''TYY? 7 	7*.++7 	7r"   r:   )r#   r$   r%   rk   ro   rr   rt   r]   rz   r}   r   r-   r"   r!   r   r      s/    @
3
EBFN77r"   r   c                       e Zd ZdZeZd fd	Zd Zd Zd Z	 e	e
j                        Z e	e
j                        Z e	e
j                        Z e	e
j"                        Z e	e
j&                        Z e	e
j*                        Zej0                  Zd Zd Zd Zd	 Zdd
ZddZddZddZ d Z!d Z"d Z#ddZ$d Z%d Z& xZ'S )	JSONFieldr8   c                     |xs t         j                  | _        |xs t         j                  | _        t        t        |   di | y rL   )rf   dumpsrg   loads_json_loadsr   r   rM   )r   
json_dumps
json_loadskwargsr    s       r!   rM   zJSONField.__init__   s7    %3%3i'1&1r"   c                 Z    |	 | j                  |      S y # t        t        f$ r |cY S w xY wr:   )r   	TypeErrorr   rE   s     r!   rS   zJSONField.python_value   s>    ''..  z* s    **c                 t    |6t        |t              s$t        j                  | j	                  |            }|S y r:   )rA   r   re   rf   rg   rE   s     r!   rG   zJSONField.db_value   s5    eT* 0 0 78L r"   c                       fd}|S )Nc                 v    t        |t        t        f      rt        || j                        }t        | |      S r:   )rA   rc   rd   AsIsrG   r   )r   rhsops     r!   innerzJSONField._e.<locals>.inner   s0    #d|,3.dB,,r"   r-   )r   r   s   ` r!   _ezJSONField._e   s    	- r"   c                 *    | j                  |       |   S r:   )Path)r   r_   s     r!   r`   zJSONField.__getitem__   s    yyt$$r"   c                 l    |D cg c]  }t        |d       }}t        j                  | g| S c c}w NF	converter)rW   re   r   r   pathsps      r!   extractzJSONField.extract   s5    49:qqE*::t,e,, ;   1c                 2    t        | dt        |d            S )Nz->Fr   r   rW   r   rQ   s     r!   extract_jsonzJSONField.extract_json   s    $eDE&BCCr"   c                 2    t        | dt        |d            S )Nz->>Fr   r   r   s     r!   extract_textzJSONField.extract_text   s    $uTU'CDDr"   c                 D    | j                  |       j                  ||      S r:   )r   rk   ri   s      r!   rk   zJSONField.append       yy%%eW55r"   c                 D    | j                  |       j                  ||      S r:   )r   rr   ri   s      r!   rr   zJSONField.insert   r   r"   c                 D    | j                  |       j                  ||      S r:   )r   rt   ri   s      r!   rt   zJSONField.set   s    yy""5'22r"   c                 D    | j                  |       j                  ||      S r:   )r   r]   ri   s      r!   r]   zJSONField.replace   s    yy&&ug66r"   c                 B    | j                  |       j                  |      S r:   )r   rz   )r   datas     r!   rz   zJSONField.update   s    yy%%d++r"   c                 p    |s| j                  |       j                         S t        j                  | g| S r:   )r   r}   re   r|   r   r   s     r!   r}   zJSONField.remove   s0    99T?))++~~d+U++r"   c                 ,    t         j                  |       S r:   )re   r   r;   s    r!   r   zJSONField.json_type       ||D!!r"   c                 8    |r| |fn| f}t        j                  | S r:   )re   r   )r   rQ   r   s      r!   r   zJSONField.length   s"    #d|$##T**r"   c                 ,    t         j                  |       S )a?  
        Schema of `json_each` and `json_tree`:

        key,
        value,
        type TEXT (object, array, string, etc),
        atom (value for primitive/scalar types, NULL for array and object)
        id INTEGER (unique identifier for element)
        parent INTEGER (unique identifier of parent element or NULL)
        fullkey TEXT (full path describing element)
        path TEXT (path to the container of the current element)
        json JSON hidden (1st input parameter to function)
        root TEXT hidden (2nd input parameter, path at which to start)
        )re   r   r;   s    r!   r   zJSONField.children   s     ||D!!r"   c                 ,    t         j                  |       S r:   )re   r   r;   s    r!   r   zJSONField.tree   r   r"   )NNr:   )(r#   r$   r%   r=   rJ   r   rM   rS   rG   r   r
   EQ__eq__NE__ne__GT__gt__GTE__ge__LT__lt__LTE__le__Field__hash__r`   r   r   r   rk   rr   rt   r]   rz   r}   r   r   r   r   r(   r)   s   @r!   r   r      s    JD2
 YFYFYFZFYFZF~~H%-DE6637,,
"+"""r"   r   c                   ,    e Zd ZdZeZd Zd Zd Zd Z	y)
JSONBFieldJSONBc                 t    |6t        |t              s$t        j                  | j	                  |            }|S y r:   )rA   r   re   r   rg   rE   s     r!   rG   zJSONBField.db_value  s5    eT*!1!1%!89L r"   c                 ,    t         j                  |       S r:   )re   rf   r;   s    r!   rf   zJSONBField.json  s    wwt}r"   c                 l    |D cg c]  }t        |d       }}t        j                  | g| S c c}w r   )rW   re   r   r   s      r!   r   zJSONBField.extract  s7    49:qqE*::-u-- ;r   c                 p    |s| j                  |       j                         S t        j                  | g| S r:   )r   r}   re   r   r   s     r!   r}   zJSONBField.remove  s0    99T?))++t,e,,r"   N)
r#   r$   r%   r=   r   r   rG   rf   r   r}   r-   r"   r!   r   r      s     JD.-r"   r   c                   D     e Zd Zd fd	Zd Zed        Zd ZddZ xZ	S )SearchFieldc                 d    |rt        dt        |      z        t        t        |   ||d       y )Nz8SearchField does not accept these keyword arguments: %s.T)	unindexedr'   null)r   sortedr   r   rM   )r   r   r'   kr    s       r!   rM   zSearchField.__init__  s@     .06q	: ; ;k4)I6A 	* 	Nr"   c                     t        | |      S r:   )match)r   terms     r!   r   zSearchField.match  s    T4  r"   c                 
   t        | d      sg| j                  j                  j                  D cg c]  }t	        |t
              r|j                    }}|j                  | j                        | _        | j                  S c c}w )N_fts_column_index)	hasattrr   _metasorted_fieldsrA   r   r   indexr   )r   fsearch_fieldss      r!   fts_column_indexzSearchField.fts_column_index   so    t01-1ZZ-=-=-K-K < *1k : VV <M <%2%8%8%CD"%%%<s   #B c                     | j                   }t        j                  | j                  j                  j
                  |||      S r:   )r   re   	highlightr   r   entity)r   leftright
column_idxs       r!   r   zSearchField.highlight(  s2    **
||DJJ,,33ZuMMr"   c                     d|cxk  rdk  st        d       t        d      | j                  }t        j                  | j                  j
                  j                  |||||      S )Nr   A   z/max_tokens must be between 1 and 64 (inclusive))r   r   re   snippetr   r   r   )r   r   r   over_length
max_tokensr   s         r!   r  zSearchField.snippet,  se    J##NOO $NOO**
zz$****11:tU%z3 	3r"   )FN)z...   )
r#   r$   r%   rM   r   r   r   r   r  r(   r)   s   @r!   r   r     s-    N! & &N3r"   r   c                   (     e Zd ZddZd fd	Z xZS )VirtualTableSchemaManagerc                    | j                   j                  t        | j                   j                  j                  |            }| j                         }|j                  d       |r|j                  d       |j                  | j                         j                  d       | j                   j                  j                  }t        |t              r|j                  |      S |j                  t        |            j                  d       g }| j                   j                  }|j                  r2|j                  |j                  D cg c]  }t        |       c}       |j                  D ]u  }t        |t              s|j                   r t#        |j$                        g}	|j&                  r|	j)                  t        d             |j)                  t+        |	             w |j,                  r2|j                  |j,                  D cg c]  }t        |       c}       |r |j                  | j/                  |             |j                  t1        |            S c c}w c c}w )NzCREATE VIRTUAL TABLE zIF NOT EXISTS z USING  	UNINDEXED)r   clean_optionsr   r   options_create_contextliteralr   extension_modulerA   r   r3   prefix_argumentsextendr   r   _hiddenr   r'   r   rk   r	   	arguments_create_table_option_sqlr   )
r   safer  r4   
ext_moduler  metaarP   	field_defs
             r!   _create_virtual_tablez/VirtualTableSchemaManager._create_virtual_table5  s   ****tzz''//9; ""$+,KK()	
#djj/
')
ZZ%%66
j$'77:&&J ((-	zz  d.C.CDc!fDE '' 	2E%*.%-- 1 123I  [!12Xi01	2 >>dnn=c!f=>T::7CDww'	233! E >s   	I I%c                     t        | j                  t              r | j                  |fi |S t	        t
        |   |fi |S r:   )
issubclassr   VirtualModelr  r   r  _create_table)r   r  r  r    s      r!   r  z'VirtualTableSchemaManager._create_table`  sI    djj,/-4--d>g>>.C 	r"   T)r#   r$   r%   r  r  r(   r)   s   @r!   r  r  4  s    )4V r"   r  c                   0    e Zd Z G d d      Zed        Zy)r  c                        e Zd ZdZdZdZdZeZy)VirtualModel.MetaNF)	r#   r$   r%   r  r  r  primary_keyr  schema_manager_classr-   r"   r!   Metar#  i  s    	8r"   r&  c                     |S r:   r-   )clsr  s     r!   r  zVirtualModel.clean_optionsp  s    r"   N)r#   r$   r%   r&  classmethodr  r-   r"   r!   r  r  h  s     9 9  r"   r  c                       e Zd Zed        Zy)BaseFTSModelc                 *   |j                  d      }|j                  d      }|j                  d      }t        |t              r|dk(  rd|d<   nt        |t              rt	        d      |rqt        |t
        t        f      r)dj                  |D cg c]  }t        |       c}      }nt        |t              rt        |      }d|j                  d	      z  |d<   |r/| j                  j                  j                         d
k(  rd|z  |d<   |S c c}w )NcontentprefixtokenizerV   z''z[The content option must be a Model, a table-name string, or the empty string (contentless).,z'%s'z' fts5z"%s")getrA   rB   r   ImproperlyConfiguredrc   tuplerX   r\   stripr   r  lower)r(  r  r-  r.  r/  is         r!   r  zBaseFTSModel.clean_optionsv  s    ++i(X&;;z*gs#2!%GI'& (? @ @ &4-06":a3q6":;FC(V &d); ;GH		2288:fD #)8"3GJ #;s   DN)r#   r$   r%   r)  r  r-   r"   r!   r+  r+  u  s     r"   r+  c                   N   e Zd ZdZ e       Z G d d      Zed        Zed        Z	ed        Z
ed        Zedd       Zedd	       Zed
        Zed        Zed        Zed        Zed        Zed        Ze	 	 dd       Ze	 	 dd       Ze	 	 dd       Ze	 	 dd       Zy)FTSModelz
    VirtualModel class for creating tables that use the FTS4 search
    extension. To use FTS3, set ``Meta.extension_module = 'FTS3'``.
    c                       e Zd Zdez  Zy)FTSModel.MetazFTS%sN)r#   r$   r%   FTS_VERSIONr  r-   r"   r!   r&  r;    s    "[0r"   r&  c           	          | j                   j                  }| j                   j                  j                  d|d|d|d      }|j	                         S )NzINSERT INTO (z
) VALUES('z');)r   
table_namedatabaseexecute_sqlfetchone)r(  cmdtblress       r!   _fts_cmdzFTSModel._fts_cmd  sB    ii""ii  ,,25sC@B||~r"   c                 $    | j                  d      S NoptimizerF  r(  s    r!   rI  zFTSModel.optimize      ||J''r"   c                 $    | j                  d      S NrebuildrJ  rK  s    r!   rO  zFTSModel.rebuild      ||I&&r"   c                 $    | j                  d      S )Nintegrity-checkrJ  rK  s    r!   integrity_checkzFTSModel.integrity_check  s    ||-..r"   c                 0    | j                  d|d|      S )Nzmerge=r0  rJ  )r(  blockssegmentss      r!   mergezFTSModel.merge  s    ||VX>??r"   c                 :    | j                  d|xr dxs dz        S )Nzautomerge=%s10rJ  )r(  states     r!   	automergezFTSModel.automerge  s    ||Nem.BsCDDr"   c                 B    t        | j                  j                  |      S zU
        Generate a `MATCH` expression appropriate for searching this table.
        r   r   r   r(  r   s     r!   r   zFTSModel.match      
 SYY%%t,,r"   c                     t         j                  | j                  j                  t              }t        j
                  |g| S r:   )re   	matchinfor   r   FTS3_MATCHINFOfts_rank)r(  weightsrc  s      r!   rankzFTSModel.rank  s0    LL!1!1>B	{{9/w//r"   c                     t         j                  | j                  j                  t              }t        j
                  |g| S r:   )re   rc  r   r   FTS4_MATCHINFOfts_bm25r(  rf  
match_infos      r!   bm25zFTSModel.bm25  s0    \\#))"2"2NC
{{:000r"   c                     t         j                  | j                  j                  t              }t        j
                  |g| S r:   )re   rc  r   r   ri  	fts_bm25frk  s      r!   bm25fzFTSModel.bm25f  s0    \\#))"2"2NC
||J111r"   c                     t         j                  | j                  j                  t              }t        j
                  |g| S r:   )re   rc  r   r   ri  
fts_lucenerk  s      r!   lucenezFTSModel.lucene  s0    \\#))"2"2NC
}}Z2'22r"   c                    |s |       }nt        |t              rqg }| j                  j                  D ]P  }	t        |	t              r|j                  |	|j                  |	j                  d            }
|j                  |
       R  || }n || }d}|}|r| |j                  |      f}|r|st        |      } | j                  | j                  | j                  |            j                  |      S )N      ?r-   )rA   rd   r   r   r   r2  r   rk   aliasr3   selectwherer   order_by)r(  r   rf  
with_scorescore_aliasscore_fnexplicit_orderingrg  weight_argsrP   field_weight	selectionry  s                r!   _searchzFTSModel._search  s     :D&K00 1eZ0  '{{5'++ejj#2NO""<01 [)DW%D	djj56I/;'H$syy'(#	%r"   Nc                 B    | j                  ||||| j                  |      S 'Full-text search using selected `term`.)r  rg  r(  r   rf  rz  r{  r}  s         r!   searchzFTSModel.search  +     {{HH 	r"   c                 B    | j                  ||||| j                  |      S z:Full-text search for selected `term` using BM25 algorithm.)r  rm  r  s         r!   search_bm25zFTSModel.search_bm25  r  r"   c                 B    | j                  ||||| j                  |      S r  )r  rp  r  s         r!   search_bm25fzFTSModel.search_bm25f  s+     {{II 	r"   c                 B    | j                  ||||| j                  |      S r  )r  rs  r  s         r!   search_lucenezFTSModel.search_lucene  s+     {{JJ 	r"   )      r   NFscoreF)r#   r$   r%   __doc__r   r   r&  r)  rF  rI  rO  rS  rW  r\  r   rg  rm  rp  rs  r  r  r  r  r  r-   r"   r!   r9  r9    sv    LE1 1   ( ( ' ' / / @ @ E E - - 0 0 1 1 2 2 3 3 % %< FM!&	 	 8=;@	 	 9><A	 	 :?=B	 	r"   r9  abcdefghijklmnopqrstuvwxyzz	 ,"(){}*:_+0123456789   c              #   V   K   | ]!  }t        |      t        vst        |       # y wr:   )chr	_alphanum).0r   s     r!   	<genexpr>r  )  s     K3q63JSVKs   ))   z [^\s"]+|"[^"\\]*(?:\\.[^"\\]*)*"c                      e Zd ZdZ e       Z G d d      ZddddZed        Z	ed	        Z
ed
        Ze ed      fd       Zed        Zed        Zed        Zed        Ze	 	 d d       Ze	 	 d d       Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed        Zed!d       Zed"d       Z y)#	FTS5Modela  
    Requires SQLite >= 3.9.0.

    Table options:

    content: table name of external content, or empty string for "contentless"
    content_rowid: column name of external content primary key
    prefix: integer(s). Ex: '2' or '2 3 4'
    tokenize: porter, unicode61, ascii. Ex: 'porter unicode61'

    The unicode tokenizer supports the following parameters:

    * remove_diacritics (1 or 0, default is 1)
    * tokenchars (string of characters, e.g. '-_'
    * separators (string of characters)

    Parameters are passed as alternating parameter name and value, so:

    {'tokenize': "unicode61 remove_diacritics 0 tokenchars '-_'"}

    Content-less tables:

    If you don't need the full-text content in its original form, you can
    specify a content-less table. Searches and auxiliary functions will work
    as usual, but the only values returned when SELECT-ing can be rowid. Also
    content-less tables do not support UPDATE or DELETE, unless created with
    the contentless_delete=1 option (sqlite >= 3.43).

    External content tables:

    You can set up triggers to sync these, e.g.

    -- Create a table. And an external content fts5 table to index it.
    CREATE TABLE tbl(a INTEGER PRIMARY KEY, b);
    CREATE VIRTUAL TABLE ft USING fts5(b, content='tbl', content_rowid='a');

    -- Triggers to keep the FTS index up to date.
    CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN
      INSERT INTO ft(rowid, b) VALUES (new.a, new.b);
    END;
    CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN
      INSERT INTO ft(ft, rowid, b) VALUES('delete', old.a, old.b);
    END;
    CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN
      INSERT INTO ft(ft, rowid, b) VALUES('delete', old.a, old.b);
      INSERT INTO ft(rowid, b) VALUES (new.a, new.b);
    END;

    Note: with sqlite's default recursive_triggers=off, INSERT OR REPLACE on
    the content table skips the delete trigger and corrupts the index. Enable
    PRAGMA recursive_triggers if REPLACE may be used.

    Built-in auxiliary functions:

    * bm25(tbl[, weight_0, ... weight_n])
    * highlight(tbl, col_idx, prefix, suffix)
    * snippet(tbl, col_idx, prefix, suffix, ?, max_tokens)
    c                       e Zd ZdZy)FTS5Model.Metar1  N)r#   r$   r%   r  r-   r"   r!   r&  r  n  s    !r"   r&  zQBesides the implicit `rowid` column, all columns must be instances of SearchFieldz3Secondary indexes are not supported for FTS5 modelsz4FTS5 models must use the default `rowid` primary key)r=   r   pkc                    | j                   j                  j                  dk7  rt        | j                  d         | j                   j
                  j                         D ]0  }t        |t        t        f      rt        | j                  d          | j                   j                  rt        | j                  d         y )Nr   r  r=   r   )r   r$  r   r3  _error_messagesfieldsvaluesrA   r   r   indexes)r(  rP   s     r!   validate_modelzFTS5Model.validate_modelx  s     99  %%0&s':':4'@AAYY%%,,. 	NEek:%>?*3+>+>|+LMM	N 99&s':':7'CDD r"   c                    t         j                  d d t        k  ryt        j                  d      }	 |j	                  d       |j                          y#  	 |j                  d       |j                  d       | j                  j                  j                  d       n#  Y Y |j                          yxY wY vxY w# |j                          w xY w)Nr   Fz:memory:z0CREATE VIRTUAL TABLE fts5test USING fts5 (data);Tr1  )
r   sqlite_version_infoFTS5_MIN_SQLITE_VERSIONconnectexecuteenable_load_extensionload_extensionr   r@  close)r(  tmp_dbs     r!   fts5_installedzFTS5Model.fts5_installed  s    &&r*-DD ,	NNMN LLN	::,,T2%%f- 		""11&9 LLN :LLNs;   A B9"B9&B9B4!B9"B< 4B97B< <Cc                     t         j                  |       }|D ]9  }|j                  d      r|j                  d      r&t	        |      t
        z  s9 y y)z
        Simple helper function to indicate whether a search query is a
        valid FTS5 query. Note: this simply looks at the characters being
        used, and is not guaranteed to catch all problematic queries.
        r[   FT)	_quote_refindall
startswithendswithrt   _invalid_ascii)querytokenstokens      r!   validate_queryzFTS5Model.validate_query  sS     ""5) 	E$)<5zN*		
 r"   r  c                 X   g }d}t         j                  |       }|D ]x  }|j                  d      r#|j                  d      r|j	                  |       7t        |      }|t        z  }|rd}|D ]  }|j                  ||      } |j	                  |       z |rdj                  |      S | S )z2
        Clean a query of invalid tokens.
        Fr[   Tr
  )	r  r  r  r  rk   rt   r  r]   rX   )	r  r]   accumany_invalidr  r  	token_setinvalid_for_tokencs	            r!   clean_queryzFTS5Model.clean_query  s    
 ""5) 
	 E$)<U#E
I )N : "* 6A!MM!W5E6LL
	  88E?"r"   c                     | j                   j                  D cg c]*  }t        |t              r|j                  s|j
                  , }}t        j                  ||      S c c}w )z
        Translate a search-box query (quoted phrases, AND/OR/NOT, -exclusion,
        column:filters, parentheses) into an FTS5 query.
        )r   r   rA   r   r   r'   _fts_parserparse)r(  r  r   columnss       r!   	web_queryzFTS5Model.web_query  sZ     +.))*A*A FQ K0 == F F  00Fs   /A c                 B    t        | j                  j                  |      S r^  r_  r`  s     r!   r   zFTS5Model.match  ra  r"   c                 :    |r | j                   | S t        d      S )Nrg  )rm  r3   )r(  r   s     r!   rg  zFTS5Model.rank  s    "&xsxx7CK7r"   c                 V    t        j                  | j                  j                  g| S r:   )re   rm  r   r   )r(  rf  s     r!   rm  zFTS5Model.bm25  s     wwsyy''2'22r"   Nc                 R    | j                  t        j                  |      ||||      S r  )r  r  r  r  s         r!   r  zFTS5Model.search  s/     !!$' 	r"   c           
         |st        d      }nt        |t              rg }| j                  j                  D ]N  }t        |t
              s|j                  |j                  ||j                  |j                  d                   P t        j                  | j                  j                  g| }n*t        j                  | j                  j                  g| }d}	|}
|r| |j                  |      f}	|r|st        |      }
 | j                  |	 j                  | j                  t         j#                  |                  j%                  |
      S )r  rg  ru  r-   )r3   rA   rd   r   r   r   rk   r2  r   re   rm  r   rv  rw  rx  r   r  r  ry  )r(  r   rf  rz  r{  r}  rg  r~  rP   r  ry  s              r!   r  zFTS5Model.search_bm25  s    v;D&K00 J e[1&&E7;;uzz3+GHJ	J 77399++:k:D77399++6g6D	djj56I/;'H$syy!6!6t!<=>(#	%r"   c           	      P   | j                   j                  }|g}|g}|j                         D ]0  \  }}|j                  t	        |             |j                  |       2 t        t        d      | j                   j                  t        |      t        d      t        |      f      S )NzINSERT INTOVALUES)r   r   itemsrk   r   r	   r3   r   )r(  rC  extra_paramsrD  r  r  keyrF   s           r!   _fts_cmd_sqlzFTS5Model._fts_cmd_sql  s    ii%&,,. 	!JCNN6#;'MM% 	! IIW%MV$& ' 	'r"   c                 r     | j                   |fi |}| j                  j                  j                  |      S r:   )r  r   r@  r  )r(  rC  r  r  s       r!   rF  zFTS5Model._fts_cmd  s4       55yy!!))%00r"   c                 l    d|cxk  rdk  st        d       t        d      | j                  d|      S )Nr   @   zlevel must be between 0 and 64r\  rg  )r   rF  )r(  levels     r!   r\  zFTS5Model.automerge  s?    U b =>> !=>>||Ke|44r"   c                 (    | j                  d|      S )NrW  r  rJ  )r(  npagess     r!   rW  zFTS5Model.merge  s    ||G&|11r"   c                 $    | j                  d      S rH  rJ  rK  s    r!   rI  zFTS5Model.optimize!  rL  r"   c                 $    | j                  d      S rN  rJ  rK  s    r!   rO  zFTS5Model.rebuild%  rP  r"   c                 (    | j                  d|      S )Npgszr  rJ  )r(  r  s     r!   set_pgszzFTS5Model.set_pgsz)  s    ||F|..r"   c                 (    | j                  d|      S )Nrg  r  rJ  )r(  rank_expressions     r!   set_rankzFTS5Model.set_rank-  s    ||F|99r"   c                 $    | j                  d      S )Nz
delete-allrJ  rK  s    r!   
delete_allzFTS5Model.delete_all1  s    ||L))r"   c                    i }| j                   j                  D ]  }t        |t              s|j                  |v r)|j                  |j                        ||j                  <   K|j                  |v r)|j                  |j                        ||j                  <   |j                  rt        d|j                  z         |r&t        ddj                  t        |            z         | j                  dd|i|S )a  
        Remove a row using the fts5 'delete' command, passing the values
        exactly as they were indexed. This is how rows are removed from
        external-content and contentless tables, which cannot look up the
        old values themselves.
        zIdelete_command() requires the value of "%s" as it was originally indexed.z4delete_command() received unrecognized column(s): %sz, r   )delete)r   r   rA   r   r   popr'   r   r   rX   r   rF  )r(  r   r  r  rP   s        r!   delete_commandzFTS5Model.delete_command5  s     YY,, 	OEe[1zzV#+1::ejj+Ae''(""f,+1::e6G6G+He''(__ ! "ACH::"N O O	O  "$(IIfVn$=> ? ?s||;E;U;;r"   c                 (    | j                  d|      S )NrR  r  rJ  )r(  rg  s     r!   rS  zFTS5Model.integrity_checkO  s    ||-D|99r"   c                 :    dvrt        d      dk(  rdndz   G  fdd      }dk(  rd}n
d	k(  rd
}nd}|D ci c]  }||dv r
t               n	t                }}t               |d<   ||d<   t	        d j
                  z  t        f|      S c c}w )N)rowcolinstancez5table_type must be either "row", "col" or "instance".r  _vz_v_%sc                       e Zd ZW  j                  j                  ZW xs W  j                  j
                  W z   Zej                  W  j                  j                   e	W             Z
y)"FTS5Model.VocabModel.<locals>.MetaN)r#   r$   r%   r   r@  r?  re   	fts5vocabr   r3   r  )r(  suffixtable
table_types   r!   r&  r  ]  sN    yy))H?#))"6"6"?J!||		  J !r"   r&  )r   doccntr  )r   r  r  r  )r   r  r  offset)r   r  r   z%sVocab)r   	TextFieldIntegerFieldr   r   r#   r  )r(  r  r  r&  r  r  attrsr  s   ```    @r!   
VocabModelzFTS5Model.VocabModelS  s    77 + , ,
 $u,'J2F	! 	! ,G5 3G6G "# 1#7IK\^K # ##gf I,|ouEE#s    Br  )r   )r  N)!r#   r$   r%   r  r   r   r&  r  r)  r  r  staticmethodr  r  r  r  r   rg  rm  r  r  r  rF  r\  rW  rI  rO  r  r  r  r  rS  r  r-   r"   r!   r  r  /  s   9x LE" "5FD	O E E  *   #&r7  . 1 1 - - 8 8 3 3 FM!&  8=;@% %: ' ' 1 1 5 5
 2 2 ( ( ' ' / / : : * * < <2 : : F Fr"   r  MATCHc                 8    t        | t        j                  |      S r:   )r   r
   r  )lhsr   s     r!   r   r   w  s    c288S))r"   )4rf   repeeweer   r   r   r   r   r	   r
   r   r   	playhouser   r  rd  ri  r<  r  	AutoFieldr   r+   r/   DecimalFieldr7   DateTimeFieldr?   rJ   r   r  r   r   r   r   SchemaManagerr  Modelr  r+  r9  	_alphabetrt   upperr  r  ranger  compiler  r  r  r   r-   r"   r!   <module>r
     s    	   #        / # 9 91 1; ;"L "
} $;7z ;7z7 7>\"	 \"~- -.3% 3>1 1h
5 
< >M| M` )	*+^"#$ #b'_	 KU3ZKKBJJ:;	CF CFL
 *r"   