
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
U
    SW                     @   sd  d Z ddlZddlZddlZddlZddlZddlZddlZzddlZ	W n e
k
rd   ddl	Z	Y nX zddlmZ W n e
k
r   Y nX ddlT 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dlmZ ddlmZ zddlmZ W n e
k
rN   dZY nX ejd dkrdeZdZ dZ!ej"dd dkrdpdZ#dZ$G dd deZ%G dd deZ&G dd de'Z(G dd  d e)Z*G d!d" d"e+Z,G d#d$ d$e-Z.G d%d& d&e.e+Z/G d'd( d(e.e0Z1G d)d* d*e.e2Z3G d+d, d,e.e4Z5G d-d. d.e6Z7G d/d0 d0e7Z8G d1d2 d2e8Z9d3Z:e;d4d5d6d7e<d8d9d:d;d<d=d>d?d@ge;dAB e;e:B e;e:= B Z>e;dBdC e?dDD Z@eAdEZBG dFdG dGe8ZCd]dHdIZDG dJdK dKeZEejFdLdMdNdO ZGG dPdQ dQeHZIG dRdS dSeZJdTe_KeILejKdUi dVdT ZMdWdX ZNdYdZ ZOd[d\ ZPdS )^a  
Sqlite3 extensions
==================

* Define custom aggregates, collations and functions
* Basic support for virtual tables
* Basic support for FTS3/4
* Specify isolation level in transactions

Example usage of the Full-text search:

class Document(FTSModel):
    title = TextField()  # type affinities are ignored in FTS
    content = TextField()

Document.create_table(tokenize='porter')  # use the porter stemmer

# populate the documents using normal operations.
for doc in documents:
    Document.create(title=doc['title'], content=doc['content'])

# use the "match" operation for FTS queries.
matching_docs = Document.select().where(match(Document.title, 'some query'))

# to sort by best match, use the custom "rank" function.
best_docs = (Document
             .select(Document, Document.rank('score'))
             .where(match(Document.title, 'some query'))
             .order_by(SQL('score')))

# or use the shortcut method.
best_docs = Document.match('some phrase')
    N)TableFunction)*)EnclosedClause)Entity)
Expression)Node)OP)SqliteQueryCompiler)_AutoPrimaryKeyField)sqlite3)transaction)_sqlite_date_part)_sqlite_date_trunc)_sqlite_regexp)_sqlite_ext   ZpcnalxZpcx)r         ZFTS4ZFTS3)r   	   r   c                   @   s   e Zd ZdZdZdS )
RowIDFieldz
    Field used to access hidden primary key on FTS5 or any other SQLite
    table that does not have a separately-defined primary key.
    rowidN__name__
__module____qualname____doc___column_name r   r   G/opt/alt/python38/lib64/python3.8/site-packages/playhouse/sqlite_ext.pyr   O   s   r   c                   @   s   e Zd ZdZdZdS )
DocIDFieldz9Field used to access hidden primary key on FTS3/4 tables.docidNr   r   r   r   r   r   W   s   r   c                       s    e Zd ZdZ fddZ  ZS )PrimaryKeyAutoIncrementFielda  
    SQLite by default uses MAX(primary key) + 1 to set the ID on a new row.
    Using the `AUTOINCREMENT` field, the IDs will increase monotonically
    even if rows are deleted. Use this if you need to guarantee IDs are not
    re-used in the event of deletion.
    c                    s   t t| |}|tdg S )NZAUTOINCREMENT)superr!   __ddl__SQL)selfcolumn_typeddl	__class__r   r   r#   c   s    z$PrimaryKeyAutoIncrementField.__ddl__)r   r   r   r   r#   __classcell__r   r   r(   r   r!   \   s   r!   c                   @   s   e Zd Zdd Zdd Zdd Zd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dZd ddZd!ddZdS )"	JSONFieldc              	   C   s6   |d k	r2zt |W S  ttfk
r0   | Y S X d S N)jsonloads	TypeError
ValueErrorr%   valuer   r   r   python_valuei   s
    zJSONField.python_valuec                 C   s   |d k	rt |S d S r,   )r-   dumpsr1   r   r   r   db_valuep   s    zJSONField.db_valuec                 C   s   | ds|sd| S d| S )N[z$%sz$.%s)
startswithr%   pathr   r   r   
clean_patht   s    zJSONField.clean_pathNc                 C   s    |rt | | |S t | S r,   )fnZjson_array_lengthr:   r8   r   r   r   lengthy   s    zJSONField.lengthc                 C   s   t | | |S r,   )r;   Zjson_extractr:   r8   r   r   r   extract~   s    zJSONField.extractc                 C   s$   t |tttfr tt|S |S r,   )
isinstancelisttupledictr;   r-   r4   r1   r   r   r   _value_for_insertion   s    zJSONField._value_for_insertionc                 C   sl   t |}|d dkrtdg }td|dD ]0}|| ||  || ||d   q,|| f| S )N   r   z%Mismatched path and value parameters.   )lenr0   rangeappendr:   rB   )r%   r;   pairsZnpairsaccumir   r   r   _insert_like   s    zJSONField._insert_likec                 G   s   |  tj|S r,   )rK   r;   Zjson_insertr%   rH   r   r   r   insert   s    zJSONField.insertc                 G   s   |  tj|S r,   )rK   r;   Zjson_replacerL   r   r   r   replace   s    zJSONField.replacec                 G   s   |  tj|S r,   )rK   r;   Zjson_setrL   r   r   r   set   s    zJSONField.setc                    s   t j f fdd|D  S )Nc                    s   g | ]}  |qS r   )r:   ).0r9   r%   r   r   
<listcomp>   s     z$JSONField.remove.<locals>.<listcomp>)r;   Zjson_remove)r%   pathsr   rQ   r   remove   s    zJSONField.removec                 C   s    |rt | | |S t | S r,   )r;   	json_typer:   r8   r   r   r   rU      s    zJSONField.json_typec                 C   s    |rt | | |S t | 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)
        )r;   Z	json_eachr:   r8   r   r   r   children   s    zJSONField.childrenc                 C   s    |rt | | |S t | S r,   )r;   Z	json_treer:   r8   r   r   r   tree   s    zJSONField.tree)N)N)N)N)r   r   r   r3   r5   r:   r<   r=   rB   rK   rM   rN   rO   rT   rU   rV   rW   r   r   r   r   r+   h   s   



r+   c                       s.   e Zd ZdZd fdd	Z fddZ  ZS )	SearchFielda-  
    Field class to be used with full-text search extension. Since the FTS
    extensions do not support any field types besides `TEXT`, and furthermore
    do not support secondary indexes, using this field will prevent you
    from mistakenly creating the wrong kind of field on your FTS table.
    FNc                    s:   d||d}|| _ |r$tdg|d< tt| jf | d S )NT)null	db_columncoerceZ	UNINDEXEDconstraints)
_unindexedr$   r"   rX   __init__)r%   Z	unindexedrZ   r[   _kwargsr(   r   r   r^      s
    zSearchField.__init__c                    s   t t| jf |}| j|_|S r,   )r"   rX   
clone_baser]   )r%   r`   cloner(   r   r   ra      s    zSearchField.clone_base)FNN)r   r   r   r   r^   ra   r*   r   r   r(   r   rX      s   rX   c                       s    e Zd ZdZ fddZ  ZS )_VirtualFieldMixinzx
    Field mixin to support virtual table attributes that may not correspond
    to actual columns in the database.
    c                    s"   t t| || |j| d S r,   )r"   rc   add_to_class_metaremove_field)r%   model_classnamer(   r   r   rd      s    z_VirtualFieldMixin.add_to_class)r   r   r   r   rd   r*   r   r   r(   r   rc      s   rc   c                   @   s   e Zd ZdS )VirtualFieldNr   r   r   r   r   r   r   ri      s    ri   c                   @   s   e Zd ZdS )VirtualIntegerFieldNrj   r   r   r   r   rk      s    rk   c                   @   s   e Zd ZdS )VirtualCharFieldNrj   r   r   r   r   rl      s    rl   c                   @   s   e Zd ZdS )VirtualFloatFieldNrj   r   r   r   r   rm      s    rm   c                   @   s4   e Zd ZG dd dZedd Zed	ddZdS )
VirtualModelc                   @   s   e Zd ZdZdZi ZdS )zVirtualModel.MetaTN)r   r   r   Zvirtual_tableextension_moduleextension_optionsr   r   r   r   Meta   s   rq   c                 K   s   |S r,   r   )clsoptionsr   r   r   clean_options   s    zVirtualModel.clean_optionsFc                 K   s.   |r|   rd S | jjj| |d |   d S )N)rs   )table_existsre   databasecreate_table_create_indexes)rr   fail_silentlyrs   r   r   r   rw      s    zVirtualModel.create_tableN)F)r   r   r   rq   classmethodrt   rw   r   r   r   r   rn      s
   
rn   c                   @   s   e Zd Zedd ZdS )BaseFTSModelc                 K   sB   | d}| d}|r$d| |d< t|tr>|dkr>d|d< |S )Ntokenizecontentz"%s" z'')getr>   
basestring)rr   rs   r|   r}   r   r   r   rt      s    

zBaseFTSModel.clean_optionsN)r   r   r   rz   rt   r   r   r   r   r{      s   r{   c                   @   s   e Zd ZdZe ZG dd dZedd Zedd Z	edd	 Z
ed
d Zedd Zed(ddZed)ddZedd Zedd Zedd Zedd Zedd Zed*d"d#Zed+d$d%Zed,d&d'ZdS )-FTSModela_  
    VirtualModel class for creating tables that use either the FTS3 or FTS4
    search extensions. Peewee automatically determines which version of the
    FTS extension is supported and will use FTS4 if possible.

    Note: because FTS5 is significantly different from FTS3 and FTS4, there is
    a separate model class for FTS5 virtual tables.
    c                   @   s   e Zd ZeZdS )zFTSModel.MetaN)r   r   r   FTS_VERro   r   r   r   r   rq     s   rq   c                 C   s   | j jjdkrtdd S )Nr    z:FTSModel classes must use the default `docid` primary key.)re   primary_keyrh   ImproperlyConfiguredrr   r   r   r   validate_model  s    zFTSModel.validate_modelc                 C   s(   | j j}| j jd|||f }| S )Nz INSERT INTO %s(%s) VALUES('%s');)re   db_tablerv   execute_sqlfetchone)rr   cmdtblresr   r   r   _fts_cmd  s
    zFTSModel._fts_cmdc                 C   s
   |  dS )Noptimizer   r   r   r   r   r   $  s    zFTSModel.optimizec                 C   s
   |  dS )Nrebuildr   r   r   r   r   r   (  s    zFTSModel.rebuildc                 C   s
   |  dS )Nzintegrity-checkr   r   r   r   r   integrity_check,  s    zFTSModel.integrity_check      c                 C   s   |  d||f S )Nzmerge=%s,%sr   )rr   ZblocksZsegmentsr   r   r   merge0  s    zFTSModel.mergeTc                 C   s   |  d|rdpd S )Nzautomerge=%s10r   )rr   stater   r   r   	automerge4  s    zFTSModel.automergec                 C   s   t |  |S zU
        Generate a `MATCH` expression appropriate for searching this table.
        match	as_entityrr   termr   r   r   r   8  s    zFTSModel.matchc                 G   s   t jt |  tf| S r,   )r;   fts_rank	matchinfor   FTS_MATCHINFO_FORMAT_SIMPLErr   weightsr   r   r   rank?  s     zFTSModel.rankc                 G   s    t |  t}t j|f| S r,   )r;   r   r   FTS_MATCHINFO_FORMATfts_bm25rr   r   
match_infor   r   r   bm25D  s    zFTSModel.bm25c                 G   s    t |  t}t j|f| S r,   )r;   r   r   r   
fts_lucener   r   r   r   luceneI  s    zFTSModel.lucenec              
   C   s   |s| }nJt |trNg }| jjD ] }	|||	||	jd q"|| }n|| }d}
|}|rp| ||f}
|r|st|}| j	|
 
| ||S )N      ?r   )r>   rA   re   declared_fieldsrG   r   rh   aliasr$   selectwherer   order_by)rr   r   r   
with_scorescore_aliasZscore_fnexplicit_orderingr   weight_argsfield	selectionr   r   r   r   _searchN  s.    

zFTSModel._searchNFscorec                 C   s   |  ||||| j|S 'Full-text search using selected `term`.)r   r   rr   r   r   r   r   r   r   r   r   searchh  s    zFTSModel.searchc                 C   s   |  ||||| j|S z:Full-text search for selected `term` using BM25 algorithm.)r   r   r   r   r   r   search_bm25t  s    zFTSModel.search_bm25c                 C   s   |  ||||| j|S r   )r   r   r   r   r   r   search_lucene  s    zFTSModel.search_lucene)r   r   )T)NFr   F)NFr   F)NFr   F)r   r   r   r   r   r    rq   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     sR   










          r   abcdefghijklmnopqrstuvwxyz	 ,"   (){}r   :r_   +
0123456789c                 C   s    g | ]}t |tkrt |qS r   )chr	_alphanum)rP   pr   r   r   rR     s      rR      z(?:[^\s"]|"(?:\.|[^"])*")+c                   @   s   e Zd ZdZe ZG dd dZddddZedd	 Z	ed
d Z
edd ZeedfddZedd Zedd Zedd Zed-ddZed.ddZedd Zed d! Zed"d# Zed$d% Zed&d' Zed(d) Zed/d+d,ZdS )0	FTS5Modelan  
    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 it's 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.

    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(fts_idx, rowid, b) VALUES('delete', old.a, old.b);
    END;
    CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN
      INSERT INTO ft(fts_idx, rowid, b) VALUES('delete', old.a, old.b);
      INSERT INTO ft(rowid, b) VALUES (new.a, new.b);
    END;

    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                   @   s   e Zd ZdZdS )zFTS5Model.Metafts5Nr   r   r   ro   r   r   r   r   rq     s   rq   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)
field_typeindexpkc                 C   sd   | j jjdkrt| jd | j j D ] }t|tt	fs(t| jd q(| j j
r`t| jd d S )Nr   r   r   r   )re   r   rh   r   _error_messagesfieldsvaluesr>   rX   r   indexes)rr   r   r   r   r   r     s    zFTS5Model.validate_modelc              	   C   s   t jd d tk rdS t d}z\z|d W nH   zt d t d W n   Y Y W dS X | jj	d Y nX W 5 |  X dS )Nr   Fz:memory:z0CREATE VIRTUAL TABLE fts5test USING fts5 (data);Tr   )
r   sqlite_version_infoFTS5_MIN_VERSIONconnectcloseexecuteenable_load_extensionload_extensionre   rv   )rr   Ztmp_dbr   r   r   fts5_installed  s    


zFTS5Model.fts5_installedc                 C   s@   t | }|D ],}|dr(|dr(qt|t@ r dS qdS )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findallr7   endswithrO   _invalid_ascii)querytokenstokenr   r   r   validate_query  s    
zFTS5Model.validate_queryr   c           	      C   s   g }d}t | }|D ]\}|dr:|dr:|| qt|}|t@ }|rhd}|D ]}|||}qV|| q|rd|S | S )z2
        Clean a query of invalid tokens.
        Fr   Tr   )	r   r   r7   r   rG   rO   r   rN   join)	r   rN   rI   Zany_invalidr   r   Z	token_setZinvalid_for_tokencr   r   r   clean_query  s"    


zFTS5Model.clean_queryc                 C   s   t |  |S r   r   r   r   r   r   r   $  s    zFTS5Model.matchc                 G   s   |r| j | S tdS d S )Nr   )r   r$   )rr   argsr   r   r   r   +  s    
zFTS5Model.rankc                 G   s   t j|  f| S r,   )r;   r   r   r   r   r   r   r   2  s    zFTS5Model.bm25NFr   c                 C   s   |  t|||||S r   )r   r   r   r   r   r   r   r   6  s    zFTS5Model.searchc              
   C   s   |st d}nbt|tr\g }| jjD ] }|||||jd q$tj	| 
 f| }ntj	| 
 f| }d}	|}
|r| ||f}	|r|st |}
| j|	 | t||
S )r   r   r   r   )r$   r>   rA   re   r   rG   r   rh   r;   r   r   r   r   r   r   r   r   r   )rr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   A  s.    

zFTS5Model.search_bm25c           
      K   sx   |   }|g}|g}| D ] \}}|t| || qt|}ttd|   t| tdt| }	| jj	|	S )NzINSERT INTOVALUES)
r   itemsrG   r   r   Clauser$   re   rv   r   )
rr   r   Zextra_paramsr   columnsr   keyr2   Zinner_clauseclauser   r   r   r   \  s    zFTS5Model._fts_cmdc                 C   s,   d|  krdksn t d| jd|dS )Nr      zlevel must be between 0 and 16r   r   )r0   r   )rr   levelr   r   r   r   n  s    zFTS5Model.automergec                 C   s   | j d|dS )Nr   r   r   )rr   Znpagesr   r   r   r   t  s    zFTS5Model.mergec                 C   s   | j d|dS )Npgszr   r   )rr   r   r   r   r   set_pgszx  s    zFTS5Model.set_pgszc                 C   s   | j d|dS )Nr   r   r   )rr   Zrank_expressionr   r   r   set_rank|  s    zFTS5Model.set_rankc                 C   s
   |  dS )Nz
delete-allr   r   r   r   r   
delete_all  s    zFTS5Model.delete_allrowc                    s   dkrt dd }t |sG  fddd}t t t t |d}dkrbt |d< d j }t |t|tf| t	 |S )	N)r   colz)table_type must be either "row" or "col".z_vocab_model_%sc                       s8   e Zd Z jjZp jjd Ze  e	Z
dS )z"FTS5Model.VocabModel.<locals>.MetaZ_vN)r   r   r   re   rv   r   r;   Z	fts5vocabr   r$   ro   r   rr   
table_name
table_typer   r   rq     s   rq   )r   docZcntr   rq   r   z%sVocab)
r0   hasattr	BareFieldIntegerFieldr   r   setattrtypern   getattr)rr   r  r   attrrq   attrs
class_namer   r   r   
VocabModel  s     


zFTS5Model.VocabModel)NFr   F)NFr   F)r   N)r   r   r   r   r   r   rq   r   rz   r   r   staticmethodr   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r   r   r     sX   7






  
    





r   c                    s    dkr4j j D ]}|jkr|  q4qtdj jG  fdddt}G  fddd}dj }t||fd|iS )z3Model factory for the transitive closure extension.Nz,Unable to find self-referential foreign key.c                       s|   e Zd Ze Ze Ze Ze Ze Ze	 Z
G dd dZedfdd	Zedfdd	Zed fd	d
	ZdS )z&ClosureTable.<locals>.BaseClosureTablec                   @   s   e Zd ZdZdS )z+ClosureTable.<locals>.BaseClosureTable.MetaZtransitive_closureNr   r   r   r   r   rq     s   rq   NFc                    sb      | jdj| | jkd| j|k}|d k	rJ|| j|k}n|s^|| jdk}|S Ndepth)onr   )r   r  r   r   idr   rootrr   noder  include_noder   rg   r   r   r   descendants  s     
 z2ClosureTable.<locals>.BaseClosureTable.descendantsc                    s^      | jdj| | jkd| j|k}|rF|| j|k}n|sZ|| jdk}|S r  )r   r  r   r   r  r   r  r  r  r   r   	ancestors  s     
 z0ClosureTable.<locals>.BaseClosureTable.ancestorsc                    s6   |j  j}  |k}|s2||k}|S r,   )_datar   rh   r   r   )rr   r  r  Zfk_valuer   foreign_keyrg   r   r   r   siblings  s
    z/ClosureTable.<locals>.BaseClosureTable.siblings)NF)NF)F)r   r   r   rk   r  r  idcolumnparentcolumnr  rl   	tablenamerq   rz   r  r  r  r   r  r   r   BaseClosureTable  s   r   c                       s0   e Zd ZjjZjjjjj jdZdZdS )zClosureTable.<locals>.Meta)r  r  r  FN)	r   r   r   re   rv   r   r   rZ   rp   r   )r  rg   r   r   rq     s   rq   z	%sClosure)	re   relr   	rel_modelr0   r   rn   r   r  )rg   r  	field_objr   rq   rh   r   r  r   ClosureTable  s    
+
r$  c                       s4   e Zd ZdZd
 fdd	Zdd Zddd	Z  ZS )SqliteExtQueryCompilerzQ
    Subclass of QueryCompiler that can be used to construct virtual tables.
    FNc                    s|  t t| j||d}t|trpd}|jj}t|trX|j	d d t
d|g }t| }qt|j	dt
d|  nd}|r|d7 }t
||j	d< | |||}|rX|j	d	 }	t| D ]\}
}t|tr||d
k}n\t|rt|tr| }n>t|ttfr"t
ddtt| }nt|ts6t
|}tt
|
|}d|_|	j	| qt|jdd rx|j	t
d |S )N)safezCREATE VIRTUAL TABLErC   ZUSINGzUSING %szCREATE TABLEz IF NOT EXISTSr   r   z'%s'r   =Zwithout_rowidzWITHOUT ROWID)r"   r%  _create_table
issubclassrn   re   ro   r>   r   nodesr$   r   rM   rt   sortedr   Fieldr   inspectisclassModelr?   r@   r   mapstrgluerG   r  )r%   rg   r&  rs   r   	statement	extensionpartsZtable_optionsZcolumns_constraintskvoptionr(   r   r   r)    sB    
 





z$SqliteExtQueryCompiler._create_tablec                 C   s>   t |jdd }|r |jf |}ni }|r:||jf | |S )Nrp   )r  re   rt   update)r%   rg   r   Zextra_optionsZmodel_optionsrs   r   r   r   rt      s    z$SqliteExtQueryCompiler.clean_optionsc                 C   s   |  | |||S r,   )
parse_noder)  )r%   rg   r&  rs   r   r   r   rw   *  s    z#SqliteExtQueryCompiler.create_table)FN)FN)r   r   r   r   r)  rt   rw   r*   r   r   r(   r   r%    s   6
r%  F)rb   c                 C   s   t d| ddS )Nr   r~   )r3  )r   rQ   r   r   r   
disqualify.  s    r<  c                       s   e Zd ZdZeZd3 fdd	Zedd Zdd Z	d	d
 Z
dd Zdd Zdd Zd4ddZd5ddZd6ddZd7ddZd8ddZd9ddZdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd:d,d-Zd; fd.d/	Zd<d1d2Z  ZS )=SqliteExtDatabasez
    Database class which provides additional Sqlite-specific functionality:

    * Register custom aggregates, collations and functions
    * Specify a row factory
    * Advanced transactions (specify isolation level)
    Tc                    s
  t t| j|f|| i | _i | _i | _tg | _d | _t	r|rd| _
| t	jdd | t	jdd | t	jdd | t	jdd | t	jdd | t	jd	d | t	jd
d nLd| _
| tdd | tdd | tdd | tdd | td	d d S )NT	date_partrC   
date_truncregexpr   r'  r   r   Z
murmurhashrD   F)r"   r=  r^   _aggregates_collations
_functionsrO   _extensions_row_factory_c_ext_using_c_extensionsregister_functionZpeewee_date_partZpeewee_date_truncZpeewee_regexpZpeewee_rankZpeewee_luceneZpeewee_bm25Zpeewee_murmurhashr   r   r   r   r   )r%   rv   Zc_extensionsr   r`   r(   r   r   r^   ?  s*    
zSqliteExtDatabase.__init__c                 C   s   | j S r,   )rG  rQ   r   r   r   using_c_extensionsW  s    z$SqliteExtDatabase.using_c_extensionsc                 C   sJ   |  | | | | | | | | jr6| j|_| jrF| | d S r,   )_set_pragmas_load_aggregates_load_collations_load_functionsrE  row_factoryrD  _load_extensions)r%   connr   r   r   _add_conn_hooks[  s    



z!SqliteExtDatabase._add_conn_hooksc                 C   s*   | j  D ]\}\}}|||| q
d S r,   )rA  r   create_aggregate)r%   rP  rh   klass
num_paramsr   r   r   rK  e  s    z"SqliteExtDatabase._load_aggregatesc                 C   s$   | j  D ]\}}||| q
d S r,   )rB  r   create_collation)r%   rP  rh   r;   r   r   r   rL  i  s    z"SqliteExtDatabase._load_collationsc                 C   s*   | j  D ]\}\}}|||| q
d S r,   )rC  r   create_function)r%   rP  rh   r;   rT  r   r   r   rM  m  s    z!SqliteExtDatabase._load_functionsc                 C   s$   | d | jD ]}|| qd S NT)r   rD  r   )r%   rP  r5  r   r   r   rO  q  s    

z"SqliteExtDatabase._load_extensionsNr'  c                 C   s2   ||f| j |p|j < |  s.| |   d S r,   )rA  r   lower	is_closedrK  get_conn)r%   rS  rh   rT  r   r   r   register_aggregatev  s    z$SqliteExtDatabase.register_aggregatec                    s    fdd}|S )Nc                    s    |   | S r,   )r[  )rS  rh   rT  r%   r   r   	decorator|  s    z.SqliteExtDatabase.aggregate.<locals>.decoratorr   r%   rh   rT  r]  r   r\  r   	aggregate{  s    zSqliteExtDatabase.aggregatec                    s@    p|j   fdd}||_|| j < |  s<| |   d S )Nc                     s   | t d  f }t| S )Nz
collate %s)r$   r   )r   expressionsrh   r   r   
_collation  s    z8SqliteExtDatabase.register_collation.<locals>._collation)r   	collationrB  rY  rL  rZ  )r%   r;   rh   rb  r   ra  r   register_collation  s    

z$SqliteExtDatabase.register_collationc                    s    fdd}|S )Nc                    s    |   | S r,   )rd  r;   rh   r%   r   r   r]    s    z.SqliteExtDatabase.collation.<locals>.decoratorr   )r%   rh   r]  r   rf  r   rc    s    zSqliteExtDatabase.collationc                 C   s.   ||f| j |p|j< |  s*| |   d S r,   )rC  r   rY  rM  rZ  )r%   r;   rh   rT  r   r   r   rH    s    z#SqliteExtDatabase.register_functionc                    s    fdd}|S )Nc                    s    |   | S r,   )rH  re  r\  r   r   r]    s    z)SqliteExtDatabase.func.<locals>.decoratorr   r^  r   r\  r   func  s    zSqliteExtDatabase.funcc                 C   s4   | j | |  s0|  }|d || d S rW  )rD  addrY  rZ  r   r   )r%   r5  rP  r   r   r   r     s
    
z SqliteExtDatabase.load_extensionc                 C   s   | j |= d S r,   )rA  r%   rh   r   r   r   unregister_aggregate  s    z&SqliteExtDatabase.unregister_aggregatec                 C   s   | j |= d S r,   )rB  ri  r   r   r   unregister_collation  s    z&SqliteExtDatabase.unregister_collationc                 C   s   | j |= d S r,   )rC  ri  r   r   r   unregister_function  s    z%SqliteExtDatabase.unregister_functionc                 C   s   | j | d S r,   )rD  rT   )r%   r5  r   r   r   unload_extension  s    z"SqliteExtDatabase.unload_extensionc                 C   s
   || _ d S r,   )rE  )r%   r;   r   r   r   rN    s    zSqliteExtDatabase.row_factoryFc                 C   s"   |   |||\}}| ||S r,   )compilerrw   r   )r%   rg   r&  rs   sqlparamsr   r   r   rw     s    zSqliteExtDatabase.create_tablec                    s"   t |trd S tt| |||S r,   )r*  r   r"   r=  create_index)r%   rg   
field_nameuniquer(   r   r   rq    s    

  zSqliteExtDatabase.create_indexdeferredc                 C   s   |  dkstt| |S )N)rt  Z	immediateZ	exclusive)rX  AssertionErrorgranular_transaction)r%   	lock_typer   r   r   rv    s    z&SqliteExtDatabase.granular_transaction)T)Nr'  )Nr'  )N)N)Nr'  )Nr'  )FN)F)rt  )r   r   r   r   r%  compiler_classr^   propertyrI  rQ  rK  rL  rM  rO  r[  r_  rd  rc  rH  rg  r   rj  rk  rl  rm  rN  rw   rq  rv  r*   r   r   r(   r   r=  5  s2   









r=  c                   @   s   e Zd ZdddZdd ZdS )rv  rt  c                 C   s   || _ | j  | _|| _d S r,   )dbrZ  rP  rw  )r%   rz  rw  r   r   r   r^     s    zgranular_transaction.__init__c                 C   s   | j | j d S r,   )rz  beginrw  rQ   r   r   r   _begin  s    zgranular_transaction._beginN)rt  )r   r   r   r^   r|  r   r   r   r   rv    s   
rv  r   MATCHc                 C   s   t | tj|S r,   )r   r   r}  )lhsrhsr   r   r   r     s    c                    s"   t  } fddtd|dD S )Nc              	      s(   g | ] }t d  ||d  d qS )z@Ir   r   )structunpack)rP   rJ   bufr   r   rR     s     z%_parse_match_info.<locals>.<listcomp>r   r   )rE   rF   )r  bufsizer   r  r   _parse_match_info  s    r  c                 G   s   t | }d}|d d \}}|s,dg| }n$dg| }t|D ]\}}|||< q>t|D ]l}d|| d  }	t|D ]N}
||
 }|sqt|	|
d  }|||d  \}}|dkrt||t||  7 }qtqX| S )N        rC   rD   r   r   )r  	enumeraterF   float)raw_match_infor   r   r   r   r   rJ   weightZ
phrase_numZphrase_info_idxZcol_numZcol_idxx1Zx2r   r   r   r     s&    

r   c                 G   s  t | }d}d}d}td\}}}}	|| }
|| }|| }|	| }|| }|s\dg| }n(dg| }t|D ]\}}|| ||< qnt|
D ]}t|D ]}|| }|dkrqt||	|  }t|||  }|dkrd}nd| |||   }|d| |d   }t|| }t||d  }tt|| d	 |d	  d}|||  }|dkr\d}n||d  | }||| | 7 }qq| S )
z
    Usage:

        # Format string *must* be pcnalx
        # Second parameter to bm25 specifies the index of the column, on
        # the table being queries.
        bm25(matchinfo(document_tbl, 'pcnalx'), 1) AS rank
    g333333?g      ?r  r   rD   r   r   rC   g      ?)r  rF   r  r  maxmathlog)r  r   r   KBr   ZP_OZC_OZN_OZA_OZ
term_countZ	col_countZ
total_docsZL_OZX_Or   rJ   r  jZ
avg_lengthZ
doc_lengthDxZterm_frequencyZdocs_with_termZidfZdenomr  r   r   r   r     sT    	


r   )N)Qr   Zglobr.  r  osrer  sysZ
simplejsonr-   ImportErrorZvtfuncr   peeweer   r   r   r   r   r	   r
   r   r   r   r   r   	playhouser   rF  version_infor2  r   r   r   r   r   r   r   r   PrimaryKeyFieldr!   	TextFieldr+   r  rX   objectrc   ri   r  rk   	CharFieldrl   
FloatFieldrm   r0  rn   r{   r   Z	_alphabetrO   r   upperr   rF   r   compiler   r   r$  r%  extendr<  SqliteDatabaser=  rv  r}  register_opsr   r  r   r   r   r   r   r   <module>   s   !
R          

  
CH

 
 