U
    {h[                     @   s  d dl Z d dlmZ d dlmZmZmZmZ d dlm	Z	m
Z
 d dlmZmZ d dlmZ d dlmZ d dlmZmZ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#m$Z$m%Z%m&Z& d dl'm(Z(m)Z)m*Z* d dl+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1 d dl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 d dl:m;Z;m<Z<m=Z=m>Z> G dd dZ?G dd dZ@G dd de$ZAG dd deAZBG dd de%ZCG dd  d ZDG d!d" d"eDZEG d#d$ d$e#ZFeFZGdS )%    N)OrderedDict)DEFAULT_DB_ALIASNotSupportedErrorconnectionstransaction)CaseWhen)AvgCount)
LOOKUP_SEPF)BooleanField
FloatField	TextField)Cast)Length)ManagerQ)	force_str)cached_property)BaseSearchBackendBaseSearchQueryCompilerBaseSearchResultsFilterFieldError)LexemeMatchExpressionSearchQuery)AutocompleteFieldRelatedFieldsSearchFieldget_indexed_models)
IndexEntry)AndBoostMatchAllNotOrPhrase	PlainText)ORbalanced_reduceget_content_type_pk!get_descendants_content_types_pksc                   @   sb   e Zd ZdZdd Zdd Zdd Zedd	 Zed
d Z	edd Z
edd ZdddZdS )ObjectIndexerzW
    Responsible for extracting data from an object to be inserted into the index.
    c                 C   s   || _ | | _|j| _d S N)objget_search_fieldssearch_fieldsconfig)selfr1   backend r7   t/var/www/dating/data/www/fatepal.com/env/lib/python3.8/site-packages/wagtail/search/backends/database/mysql/mysql.py__init__1   s    
zObjectIndexer.__init__c                    s^   t |tr|S t |tr0d fdd|D S t |trVd fdd| D S t|S )Nz, c                 3   s   | ]}  |V  qd S r0   prepare_value.0itemr5   r7   r8   	<genexpr>;   s     z.ObjectIndexer.prepare_value.<locals>.<genexpr>c                 3   s   | ]}  |V  qd S r0   r:   r<   r?   r7   r8   r@   >   s     )
isinstancestrlistjoindictvaluesr   )r5   valuer7   r?   r8   r;   6   s    


zObjectIndexer.prepare_valuec                 c   s   t |tr"|| ||fV  nt |trD|| ||fV  npt |tr||}|d krdd S t |trx| }nt|r| }|g}|D ]"}|j	D ]}| 
||E d H  qqd S r0   )rA   r!   r;   	get_valuer   r    r   allcallablefieldsprepare_field)r5   r1   fieldZsub_objZsub_objsZ	sub_fieldr7   r7   r8   rL   B   s     






zObjectIndexer.prepare_fieldc                 C   s   t | jjS )zO
        Returns the value to use as the ID of the record in the index
        )r   r1   pkr?   r7   r7   r8   id[   s    zObjectIndexer.idc                 C   sP   g }| j D ]:}| | j|D ]&\}}t|tr|jdkr|| qq
d|S )z
        Returns all values to index as "title". This is the value of all SearchFields that have the field_name 'title'
        title r3   rL   r1   rA   r!   
field_nameappendrD   r5   textsrM   Zcurrent_fieldrG   r7   r7   r8   rP   b   s    
zObjectIndexer.titlec                 C   sP   g }| j D ]:}| | j|D ]&\}}t|tr|jdks|| qq
d|S )zr
        Returns all values to index as "body". This is the value of all SearchFields excluding the title
        rP   rQ   rR   rU   r7   r7   r8   bodyr   s    
zObjectIndexer.bodyc                 C   sF   g }| j D ]0}| | j|D ]\}}t|tr|| qq
d|S )zl
        Returns all values to index as "autocomplete". This is the value of all AutocompleteFields
        rQ   )r3   rL   r1   rA   r   rT   rD   rU   r7   r7   r8   autocomplete   s    

zObjectIndexer.autocompleteFc                 C   s&   dd |D }dd |D }d |S )zW
        Converts an array of strings into a SearchVector that can be indexed.
        c                 S   s   g | ]\}}|  |fqS r7   )stripr=   textweightr7   r7   r8   
<listcomp>   s     z+ObjectIndexer.as_vector.<locals>.<listcomp>c                 S   s   g | ]\}}|r||fqS r7   r7   rZ   r7   r7   r8   r]      s      rQ   )rD   )r5   rV   Zfor_autocompleter7   r7   r8   	as_vector   s    zObjectIndexer.as_vectorN)F)__name__
__module____qualname____doc__r9   r;   rL   r   rO   rP   rW   rX   r^   r7   r7   r7   r8   r/   ,   s   



r/   c                   @   sh   e Zd Zd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S )IndexNc                 C   sV   || _ | j j| _|d krtn|| _t| j | _| jjdkrBtdt	j
| j| _d S )Nmysqlz5You must select a MySQL database to use MySQL search.)r6   
index_namenamer   db_aliasr   
connectionvendorr   r#   _default_managerusingentries)r5   r6   rg   r7   r7   r8   r9      s    
zIndex.__init__c                 C   s   d S r0   r7   r5   modelr7   r7   r8   	add_model   s    zIndex.add_modelc                 C   s   d S r0   r7   r?   r7   r7   r8   refresh   s    zIndex.refreshFc                 C   sn   | j jtddjddtdd }|r4| j }n| j jdd}|jtddjddj|td d d	S )
a  
        Refreshes the value of the title_norm field.

        This needs to be set to 'lavg/ld' where:
         - lavg is the average length of titles in all documents (also in terms)
         - ld is the length of the title field in this document (in terms)
        rP   )title_lengthr   )Ztitle_length__gtrq   Ztitle_length__avg      ?)
title_normN)rl   annotater   filterZ	aggregater	   updater   )r5   fullZlavgrl   r7   r7   r8   _refresh_title_norms   s     

zIndex._refresh_title_normsc                 C   sN   |j | jjtdt dd}t|}| jj	|dj
|d}|  d S )NrN   	object_idrz   Zcontent_type_id__inZobject_id__in)rj   rk   rg   rt   r   r   rF   r.   rl   ru   excludedelete)r5   rn   Zexisting_pksZcontent_types_pksZstale_entriesr7   r7   r8   delete_stale_model_entries   s    
z Index.delete_stale_model_entriesc                 C   s"   t  D ]}|jjs| | qd S r0   )r"   _metaparentsr   rm   r7   r7   r8   delete_stale_entries   s    
zIndex.delete_stale_entriesc                 C   s   |  |jj|g d S r0   )	add_itemsr   rn   r5   r1   r7   r7   r8   add_item   s    zIndex.add_itemc              
   C   s   i }|D ]}|j |j|jf||j< q| jj|d}t|j| djddd}|D ]*}|| \}}	}
|j|dj	||	|
d qTg }| D ]2}||kr|| \}}	}
|
t||||	|
d q| j| |   d S )	N)content_type_idr|   rz   T)Zflatry   )rP   rX   rW   )r   rz   rP   rX   rW   )rP   rX   rW   rO   rl   ru   	frozensetkeysZvalues_listrv   rT   r#   Zbulk_createrx   )r5   content_type_pkindexersZids_and_dataZindexerZindex_entries_for_ctZindexed_idsZ
indexed_idrP   rX   rW   Zto_be_createdrz   r7   r7   r8   add_items_update_then_create   sF       
z"Index.add_items_update_then_createc                    sB   |  }|sd S  fdd|D }|r>t|} j}||| d S )Nc                    s   g | ]}t | jqS r7   )r/   r6   )r=   r1   r?   r7   r8   r]     s     z#Index.add_items.<locals>.<listcomp>)r2   r-   r   )r5   rn   Zobjsr3   r   r   Zupdate_methodr7   r?   r8   r     s    zIndex.add_itemsc                 C   s   |j  j| jd d S )Nrk   )index_entriesrI   _raw_deleterg   )r5   r>   r7   r7   r8   delete_item  s    zIndex.delete_itemc                 C   s   | j S r0   )rf   r?   r7   r7   r8   __str__  s    zIndex.__str__)N)F)r_   r`   ra   r9   ro   rp   rx   r   r   r   r   r   r   r   r7   r7   r7   r8   rc      s   

'rc   c                       s   e Zd ZdZdZeZddgZ fddZdd Z	d	d
 Z
d ddZd!ddZdd Zdd Zdd Zdd Zdd Zd"ddZdd Zdd Z  ZS )#MySQLSearchQueryCompilerandFrP   rW   c                    sD   t  j||   jd kr( _n fddjD _d S )Nc                    s   i | ]}|j | d qS ))rK   )get_search_field)r=   field_lookupZlocal_search_fieldsr5   r7   r8   
<dictcomp>.  s     z5MySQLSearchQueryCompiler.__init__.<locals>.<dictcomp>)superr9   get_search_fields_for_modelrK   r3   )r5   argskwargs	__class__r   r8   r9   #  s    
z!MySQLSearchQueryCompiler.__init__c                 C   s   |j S r0   r4   r5   r6   r7   r7   r8   
get_config5  s    z#MySQLSearchQueryCompiler.get_configc                 C   s   | j j S r0   )querysetrn   Zget_searchable_search_fieldsr?   r7   r7   r8   r   8  s    z4MySQLSearchQueryCompiler.get_search_fields_for_modelNc                 C   s~   |d kr| j }t|kr(|td\}}nd }|D ]H}t|| jrR|j|krR|  S t|tr0|j|kr0| ||j  S q0d S )N   )	r3   r   splitrA   TARGET_SEARCH_FIELD_TYPErS   r    r   rK   )r5   r   rK   Zsub_field_namerM   r7   r7   r8   r   ;  s    
z)MySQLSearchQueryCompiler.get_search_fieldc                    s>  t |trn|j }|sd S | }t| jd}|D ],}t| d}|jdkr\||M }q8||O }q8t|S t |t	rt|jddS t |t
rd}t|t j|j dS t |tr̈j|j  dS t |ttfr* fdd|jD }	t |t}
 r|
 }
|
rtd	d
 |	S tdd
 |	S td|jj d S )N)invertprefixr   r   phrase)Zsearch_typez=The Boost query is not supported by the MySQL search backend.c                    s   g | ]}j | d qS )r   build_search_query_content)r=   subqueryr   r5   r7   r8   r]     s   zGMySQLSearchQueryCompiler.build_search_query_content.<locals>.<listcomp>c                 S   s   | |@ S r0   r7   abr7   r7   r8   <lambda>      zEMySQLSearchQueryCompiler.build_search_query_content.<locals>.<lambda>c                 S   s   | |B S r0   r7   r   r7   r7   r8   r     r   z2`%s` is not supported by the MySQL search backend.)rA   r*   Zquery_stringr   popr   LAST_TERM_IS_PREFIXoperatorr   r)   r%   warningswarnRuntimeWarningr   r   r'   r$   r(   Z
subqueriesr,   NotImplementedErrorr   r_   )r5   queryr   ZtermsZ	last_termZlexemestermZ
new_lexememsgZsubquery_lexemesZis_andr7   r   r8   r   Q  sF    








z3MySQLSearchQueryCompiler.build_search_query_contentc                 C   s
   |  |S r0   r   )r5   r   r7   r7   r8   build_search_query  s    z+MySQLSearchQueryCompiler.build_search_queryc                 C   s   t dt dft ddfgS )NZindex_entries__titleZindex_entries__title_normZindex_entries__bodyrr   r   r5   search_queryr7   r7   r8   get_index_vectors  s    
z*MySQLSearchQueryCompiler.get_index_vectorsc                 C   s
   t  d S r0   r   r   r7   r7   r8   get_fields_vectors  s    z+MySQLSearchQueryCompiler.get_fields_vectorsc                 C   s"   | j d kr| |S | |S d S r0   )rK   r   r   r   r7   r7   r8   get_search_vectors  s    

z+MySQLSearchQueryCompiler.get_search_vectorsc                    s:    fdd|D }|d }|dd  D ]}||7 }q(|S )Nc                    s&   g | ]\}}j |j d | qS )r   )Zbuild_tsrankr   )r=   ZvectorZboostr4   r5   r7   r8   r]     s   zCMySQLSearchQueryCompiler._build_rank_expression.<locals>.<listcomp>r   r   r7   )r5   Zvectorsr4   Zrank_expressionsZrank_expressionZother_rank_expressionr7   r   r8   _build_rank_expression  s    
z/MySQLSearchQueryCompiler._build_rank_expressionc                 C   s:  t | jtr| j|| S t | jtr>t | jjtr>| j S t | jtrX| jj}d}n
| j}d}| |}t|| j	t
 d}tt|dddd}t|dgt dtd t|dgt d }	tjj|	d	jt| jjd
}
|s|
|}
| jr|
|	 }
n
|
|}
|
|| }
dd |
D }| jj|d}|S )NTF)columnsZoutput_field)Zthen)defaultrP   rs   rW   )Zscorer{   c                 S   s   h | ]
}|j qS r7   ry   )r=   Zindex_entryr7   r7   r8   	<setcomp>  s    z2MySQLSearchQueryCompiler.search.<locals>.<setcomp>)Zid__in)rA   r   r&   r   r'   r   noner   r   FTS_TABLE_FIELDSr   r   r   r   r   r#   objectsrt   ru   r.   rn   Zorder_by_relevanceorder_bydescr}   )r5   r4   startstopscore_fieldr   negatedr   Zmatch_expressionZscore_expressionr   Z
object_idsresultsr7   r7   r8   search  s\    
 
      


zMySQLSearchQueryCompiler.searchc                 C   s$   | | jjd | }tf ||iS )N__)Zget_attnamer   rn   r   )r5   rM   lookuprG   lhsr7   r7   r8   _process_lookup  s    z(MySQLSearchQueryCompiler._process_lookupc                 C   s@   |dkrt | }n |dkr.tdd |D }nd S |r<| }|S )NANDr+   c                 S   s   g | ]}t |qS r7   r   )r=   Zfilr7   r7   r8   r]     s     z=MySQLSearchQueryCompiler._connect_filters.<locals>.<listcomp>)r   r+   )r5   filtersZ	connectorr   qr7   r7   r8   _connect_filters  s    
z)MySQLSearchQueryCompiler._connect_filters)N)F)N)r_   r`   ra   ZDEFAULT_OPERATORr   r!   r   r   r9   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r7   r7   r   r8   r     s"   

D
Ir   c                   @   s:   e Zd ZdZeZdgZdd Zdd Zdd Z	d	d
 Z
dS )MySQLAutocompleteQueryCompilerTrX   c                 C   s   |j S r0   )autocomplete_configr   r7   r7   r8   r     s    z)MySQLAutocompleteQueryCompiler.get_configc                 C   s   | j j S r0   )r   rn   Zget_autocomplete_search_fieldsr?   r7   r7   r8   r     s    z:MySQLAutocompleteQueryCompiler.get_search_fields_for_modelc                 C   s   t ddfgS )NZindex_entries__autocompleterr   r   r   r7   r7   r8   r     s    z0MySQLAutocompleteQueryCompiler.get_index_vectorsc                 C   s
   t  d S r0   r   r   r7   r7   r8   r     s    z1MySQLAutocompleteQueryCompiler.get_fields_vectorsN)r_   r`   ra   r   r   r   r   r   r   r   r   r7   r7   r7   r8   r     s   r   c                   @   s2   e Zd ZdddZdd Zdd ZdZd	d
 ZdS )MySQLSearchResultsFc                 C   s:   |rd }d }n| j }| j}| jj| j| j||| jdS )N)r   )r   r   query_compilerr   r   r6   Z_score_field)r5   	for_countr   r   r7   r7   r8   get_queryset$  s    zMySQLSearchResults.get_querysetc                 C   s   t |  S r0   )rC   r   r?   r7   r7   r8   
_do_search3  s    zMySQLSearchResults._do_searchc                 C   s   | j dd S )NT)r   )r   countr?   r7   r7   r8   	_do_count6  s    zMySQLSearchResults._do_countTc                    s   | j  }|d kr@td  d   d | j jjj d  d| j | j | jd d }|	 j
tddd}t fd	d
|D S )Nz(Cannot facet search results with field "z!". Please add index.FilterField('z') to z.search_fields.rS   rN   r   z-countc                    s   g | ]}|  |d  fqS r   r7   )r=   resultr   r7   r8   r]   R  s     z,MySQLSearchResults.facet.<locals>.<listcomp>)r   Z_get_filterable_fieldr   r   rn   r_   r   r   r6   rF   rt   r
   r   r   )r5   rS   rM   r   r   r7   r   r8   facet;  s8    
  zMySQLSearchResults.facetN)F)r_   r`   ra   r   r   r   Zsupports_facetr   r7   r7   r7   r8   r   #  s
   
r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )MySQLSearchRebuilderc                 C   s
   || _ d S r0   )indexr5   r   r7   r7   r8   r9   W  s    zMySQLSearchRebuilder.__init__c                 C   s   | j   | j S r0   )r   r   r?   r7   r7   r8   r   Z  s    
zMySQLSearchRebuilder.startc                 C   s   | j jdd d S )NTrw   )r   rx   r?   r7   r7   r8   finish^  s    zMySQLSearchRebuilder.finishN)r_   r`   ra   r9   r   r   r7   r7   r7   r8   r   V  s   r   c                       s8   e Zd Z fddZ fddZdd Zdd Z  ZS )	MySQLSearchAtomicRebuilderc                    s&   t  | tj|jd| _d| _d S )Nr   F)r   r9   r   Zatomicrg   transaction_openedr   r   r7   r8   r9   c  s    z#MySQLSearchAtomicRebuilder.__init__c                    s   | j   d| _t  S NT)r   	__enter__r   r   r   r?   r   r7   r8   r   h  s    
z MySQLSearchAtomicRebuilder.startc                 C   s(   | j jdd | jd d d  d| _d S )NTr   F)r   rx   r   __exit__r   r?   r7   r7   r8   r   m  s    z!MySQLSearchAtomicRebuilder.finishc                 C   s   | j rd| j_|   d S r   )r   r   Zneeds_rollbackr   r?   r7   r7   r8   __del__s  s    z"MySQLSearchAtomicRebuilder.__del__)r_   r`   ra   r9   r   r   r   r   r7   r7   r   r8   r   b  s   r   c                       sr   e Zd ZeZeZeZe	Z
eZ f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  ZS )MySQLSearchBackendc                    s>   t  | |dd| _d | _d | _|ddr:| j| _d S )NZINDEXr   ZATOMIC_REBUILDF)r   r9   getre   r4   r   atomic_rebuilder_classrebuilder_class)r5   paramsr   r7   r8   r9     s    zMySQLSearchBackend.__init__Nc                 C   s
   t | |S r0   )rc   )r5   rn   rg   r7   r7   r8   get_index_for_model  s    z&MySQLSearchBackend.get_index_for_modelc                 C   s   |  |jj|jjS r0   )r   r   rn   _statedbr   r7   r7   r8   get_index_for_object  s    z'MySQLSearchBackend.get_index_for_objectc                 C   s0   dd t  D D ]}tj j|jd qd S )Nc                 S   s   g | ]}|j d kr|qS )rd   )ri   )r=   rh   r7   r7   r8   r]     s   
z2MySQLSearchBackend.reset_index.<locals>.<listcomp>r   )r   rI   r#   rj   r   alias)r5   rh   r7   r7   r8   reset_index  s    
zMySQLSearchBackend.reset_indexc                 C   s   d S r0   r7   rm   r7   r7   r8   add_type  s    zMySQLSearchBackend.add_typec                 C   s   d S r0   r7   r?   r7   r7   r8   refresh_index  s    z MySQLSearchBackend.refresh_indexc                 C   s   |  || d S r0   )r   r   r   r7   r7   r8   add  s    zMySQLSearchBackend.addc                 C   s   |r|  |d || d S )Nr   )r   r   )r5   rn   Zobj_listr7   r7   r8   add_bulk  s    zMySQLSearchBackend.add_bulkc                 C   s   |  || d S r0   )r   r   r   r7   r7   r8   r~     s    zMySQLSearchBackend.delete)N)r_   r`   ra   r   Zquery_compiler_classr   Z!autocomplete_query_compiler_classr   Zresults_classr   r   r   r   r9   r   r   r   r   r   r   r  r~   r   r7   r7   r   r8   r   z  s   
r   )Hr   collectionsr   Z	django.dbr   r   r   r   Zdjango.db.modelsr   r   Zdjango.db.models.aggregatesr	   r
   Zdjango.db.models.constantsr   Zdjango.db.models.expressionsr   Zdjango.db.models.fieldsr   r   r   Z%django.db.models.functions.comparisonr   Zdjango.db.models.functions.textr   Zdjango.db.models.managerr   Zdjango.db.models.query_utilsr   Zdjango.utils.encodingr   Zdjango.utils.functionalr   Zwagtail.search.backends.baser   r   r   r   Z,wagtail.search.backends.database.mysql.queryr   r   r   Zwagtail.search.indexr   r    r!   r"   Zwagtail.search.modelsr#   Zwagtail.search.queryr$   r%   r&   r'   r(   r)   r*   Zwagtail.search.utilsr+   r,   r-   r.   r/   rc   r   r   r   r   r   r   ZSearchBackendr7   r7   r7   r8   <module>   s<   $m  u32