
    win*                      d dl mZ d dl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mZ d dlmZmZmZmZmZmZmZmZmZmZmZmZmZ d d	l m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( e	rej)        d
k    rd dlm*Z* nd dl+m*Z* dZ,dZ- edd          Z. G d de          Z/ G d de/          Z0 G d d          Z1 G d de1          Z2 G d de/          Z3d;d!Z4 G d" d#          Z5d<d%Z6 G d& d'          Z7e3Z8 G d( d)          Z9 G d* d+e/e          Z: G d, de/e          Z; G d- d.ee.                   Z< G d/ d0          Z= G d1 d2e=          Z> G d3 d4e=          Z? G d5 d6          Z@ G d7 d8          ZA G d9 d:          ZBdS )=    )annotationsN)Sequence)copy)reduce)TYPE_CHECKINGAnyGenericTypeVar)DialectsJoinTypeReferenceOptionSetOperation)ArithmeticExpression	CriterionEmptyCriterionFieldFunctionIndexNodePeriodCriterionRollupStarTermTupleValueWrapper)JoinExceptionQueryExceptionRollupExceptionSetOperationExceptionbuilderformat_alias_sqlformat_quotesignore_copy)      )SelfzTimothy Heysztheys@kayak.comQBQueryBuilder)boundc                      e Zd ZddZedd            Zdd	Zedd            Ze	dd            Z
e	dd            ZddZdS )
SelectablealiasstrreturnNonec                    || _         d S Nr,   selfr,   s     A/var/www/icac/venv/lib/python3.11/site-packages/pypika/queries.py__init__zSelectable.__init__2   s    


    c                    || _         d S r1   r2   r3   s     r5   as_zSelectable.as_5   s    


r7   namer   c                $    t          ||           S )Ntabler   r4   r:   s     r5   fieldzSelectable.field9   s    T&&&&r7   r   c                     t          |           S r1   )r   r4   s    r5   starzSelectable.star<   s    Dzzr7   c                ,    |                      |          S r1   r@   r?   s     r5   __getattr__zSelectable.__getattr__@       zz$r7   c                ,    |                      |          S r1   rE   r?   s     r5   __getitem__zSelectable.__getitem__D   rG   r7   c                    | j         S r1   r2   rB   s    r5   get_table_namezSelectable.get_table_nameH   s
    zr7   N)r,   r-   r.   r/   )r:   r-   r.   r   )r.   r   r.   r-   )__name__
__module____qualname__r6   r    r9   r@   propertyrC   r#   rF   rI   rK    r7   r5   r+   r+   1   s               W' ' ' '    X       [        [      r7   r+   c                  :     e Zd Zdd fdZddZddZddZ xZS )AliasedQueryNr:   r-   querySelectable | Noner.   r/   c                h    t                                          |           || _        || _        d S )Nr2   )superr6   r:   rT   )r4   r:   rT   	__class__s      r5   r6   zAliasedQuery.__init__M   s0    t$$$	


r7   kwargsr   c                B    | j         | j        S  | j         j        di |S NrQ   )rT   r:   get_sqlr4   rY   s     r5   r\   zAliasedQuery.get_sqlR   s-    :9!tz!++F+++r7   otherboolc                L    t          |t                    o| j        |j        k    S r1   )
isinstancerS   r:   r4   r^   s     r5   __eq__zAliasedQuery.__eq__W   s     %..J49
3JJr7   intc                D    t          t          | j                            S r1   )hashr-   r:   rB   s    r5   __hash__zAliasedQuery.__hash__Z   s    C	NN###r7   r1   )r:   r-   rT   rU   r.   r/   rY   r   r.   r-   )r^   rS   r.   r_   r.   rd   )rM   rN   rO   r6   r\   rc   rg   __classcell__rX   s   @r5   rS   rS   L   s              
, , , ,
K K K K$ $ $ $ $ $ $ $r7   rS   c                  J    e Zd ZdddZddZddZedd            ZdddZdS )SchemaNr:   r-   parentSchema | Noner.   r/   c                "    || _         || _        d S r1   )_name_parent)r4   r:   rn   s      r5   r6   zSchema.__init___   s    
r7   r^   r_   c                l    t          |t                    o| j        |j        k    o| j        |j        k    S r1   )ra   rm   rq   rr   rb   s     r5   rc   zSchema.__eq__c   s0    %((hTZ5;-Fh4<[`[hKhhr7   c                .    |                      |           S r1   rc   rb   s     r5   __ne__zSchema.__ne__f       ;;u%%%%r7   itemTablec                $    t          ||           S )Nschemary   r4   rx   s     r5   rF   zSchema.__getattr__i   s    T$''''r7   
quote_char
str | NonerY   r   c                    t          | j        |          }| j        )d                     | j        j        dd|i||          S |S )Nz{parent}.{schema}r   )rn   r|   rQ   )r"   rq   rr   formatr\   )r4   r   rY   
schema_sqls       r5   r\   zSchema.get_sqlm   s`    "4:z::
<#&--+t|+LLzLVLL! .   
 r7   r1   )r:   r-   rn   ro   r.   r/   )r^   rm   r.   r_   )rx   r-   r.   ry   r   r   rY   r   r.   r-   )	rM   rN   rO   r6   rc   rv   r#   rF   r\   rQ   r7   r5   rm   rm   ^   s            i i i i& & & & ( ( ( [(	 	 	 	 	 	 	r7   rm   c                  &    e Zd Zedd            ZdS )Databaserx   r-   r.   rm   c                $    t          ||           S N)rn   rm   r~   s     r5   rF   zDatabase.__getattr__z   s    d4((((r7   N)rx   r-   r.   rm   )rM   rN   rO   r#   rF   rQ   r7   r5   r   r   y   s2        ) ) ) [) ) )r7   r   c                       e Zd Zed'd            Z	 	 	 d(d) fdZd*dZd+dZed,d            Z	ed-d            Z
d*dZd.dZd*dZd/dZd0d Zd1d$Zd2d%Zd1d&Z xZS )3ry   r|   "str | list | tuple | Schema | Noner.   c                    t          | t                    r| S t          | t          t          f          r-t	          d | dd          t          | d                             S | t          |           S d S )Nc                $    t          ||           S r   r   )objss     r5   <lambda>z$Table._init_schema.<locals>.<lambda>   s    #)>)>)> r7      r   )ra   rm   listtupler   r{   s    r5   _init_schemazTable._init_schema   sv     ff%% 	MftUm,, 	_>>qrr
FSYZ[S\L]L]^^^&>>!tr7   Nr:   r-   Schema | str | Noner,   r   	query_clstype[Query] | Noner/   c                   t                                          |           || _        |                     |          | _        |pt
          | _        d | _        d | _        t          | j        t
                    st          d          d S )Nz,Expected 'query_cls' to be subclass of Query)rW   r6   _table_namer   _schemaQuery
_query_cls_for_for_portion
issubclass	TypeError)r4   r:   r|   r,   r   rX   s        r5   r6   zTable.__init__   s     	((00#,u	 $/511 	LJKKK	L 	Lr7   c                    | j         p| j        S r1   )r,   r   rB   s    r5   rK   zTable.get_table_name   s    z-T--r7   rY   r   c                   |                     d          }t          | j        |          }| j        'd                     | j        j        di ||          }| j        r(d                    | | j        j        di |          }n.| j        r'd                    | | j        j        di |          }t          || j	        fi |S )Nr   z{schema}.{table})r|   r=   z{table} FOR {criterion})r=   	criterionz"{table} FOR PORTION OF {criterion}rQ   )
getr"   r   r   r   r\   r   r   r!   r,   )r4   rY   r   	table_sqls       r5   r\   zTable.get_sql   s    ZZ--
!$"2J??	<#*119M9M9W9WPV9W9W_h1iiI9 	188yTeTXT]TeToTohnToTo8ppII 	<CC+D4+<+D+N+Nv+N+N D  I  	4:@@@@@r7   temporal_criterionr   c                l    | j         rt          d          | j        rt          d          || _         d S )N)'Query' object already has attribute for_0'Query' object already has attribute for_portion)r   AttributeErrorr   )r4   r   s     r5   for_z
Table.for_   sB    9 	N !LMMM 	U !STTT&			r7   period_criterionr   c                l    | j         rt          d          | j        rt          d          || _         d S )Nr   r   )r   r   r   )r4   r   s     r5   for_portionzTable.for_portion   sE     	U !STTT9 	N !LMMM,r7   c                .    |                      d          S N"r   r\   rB   s    r5   __str__zTable.__str__       ||s|+++r7   r_   c                    t          |t                    sdS | j        |j        k    rdS | j        |j        k    rdS | j        |j        k    rdS dS NFT)ra   ry   r   r   r,   rb   s     r5   rc   zTable.__eq__   s\    %'' 	5u0005<5=((5:$$5tr7   c                    | j         r d                    | j        | j                   S d                    | j                  S )NzTable('{}', schema='{}')zTable('{}'))r   r   r   rB   s    r5   __repr__zTable.__repr__   s?    < 	U-44T5Et|TTT##D$4555r7   r^   c                .    |                      |           S r1   ru   rb   s     r5   rv   zTable.__ne__   rw   r7   rd   c                :    t          t          |                     S r1   )rf   r-   rB   s    r5   rg   zTable.__hash__   s    CIIr7   terms'int | float | str | bool | Term | Fieldr(   c                F     | j                             |           j        | S )a  
        Perform a SELECT operation on the current table

        :param terms:
            Type:  list[expression]

            A list of terms to select. These can be any type of int, float, str, bool or Term or a Field.

        :return:  QueryBuilder
        )r   from_selectr4   r   s     r5   r   zTable.select   s$     2t$$T**1599r7   c                6    | j                             |           S )za
        Perform an UPDATE operation on the current table

        :return: QueryBuilder
        )r   updaterB   s    r5   r   zTable.update   s     %%d+++r7   c                F     | j                             |           j        | S )a  
        Perform an INSERT operation on the current table

        :param terms:
            Type: list[expression]

            A list of terms to select. These can be any type of int, float, str, bool or  any other valid data

        :return: QueryBuilder
        )r   intoinsertr   s     r5   r   zTable.insert   s$     1t##D))0%88r7   )r|   r   r.   r   NNN)
r:   r-   r|   r   r,   r   r   r   r.   r/   rL   rh   )r   r   r.   r/   )r   r   r.   r/   )r.   r_   )r^   r   r.   r_   ri   )r   r   r.   r(   r.   r(   )rM   rN   rO   staticmethodr   r6   rK   r\   r    r   r   r   rc   r   rv   rg   r   r   r   rj   rk   s   @r5   ry   ry      s~       	 	 	 \	 '+ (,L L L L L L L . . . .A A A A  ' ' ' W' - - - W-, , , ,   6 6 6 6
& & & &   : : : :, , , ,9 9 9 9 9 9 9 9r7   ry   namestuple[str, str] | strrY   r   r.   list[Table]c            	        g }| D ]}t          |t                    rYt          |          dk    rFt          |d         |d         |                    d          |                    d                    }n8t          ||                    d          |                    d                    }|                    |           |S )z
    Shortcut to create many tables. If `names` param is a tuple, the first
    position will refer to the `_table_name` while the second will be its `alias`.
    Any other data structure will be treated as a whole as the `_table_name`.
       r   r   r|   r   )r:   r,   r|   r   )r:   r|   r   )ra   r   lenry   r   append)r   rY   tablesr:   ts        r5   make_tablesr      s     F  dE"" 	s4yyA~~!W1gzz(++ **[11	  AA zz(++ **[11  A
 	aMr7   c                  :    e Zd ZdZ	 	 	 dddZddZddZddZdS )ColumnzRepresents a column.Ncolumn_namer-   column_typer   nullablebool | NonedefaultAny | Term | Noner.   r/   c                    || _         || _        || _        |t          |t                    r|nt          |          | _        d S r1   )r:   typer   ra   r   r   r   )r4   r   r   r   r   s        r5   r6   zColumn.__init__  sD      		 ")/Z5N5N/wwT`ahTiTir7   rY   r   c                    |                     d          }d                    t          | j        |                    }|S )Nr   z{name}r:   )r   r   r"   r:   )r4   rY   r   
column_sqls       r5   get_name_sqlzColumn.get_name_sql'  sB    ZZ--
__ty*55 % 
 

 r7   c                8   d                      | j        di || j        rd                     | j                  nd| j        d                     | j        rdnd          nd| j        r(d                     d | j        j        di |z             nd          }|S )	Nz{name}{type}{nullable}{default}z {} NULLzNOT NULLzDEFAULT )r:   r   r   r   rQ   )r   r   r   r   r   r\   )r4   rY   r   s      r5   r\   zColumn.get_sql0  s    6=="",,V,,,0I=di(((2NRmNgU\\DM"I&&zJJJmoQUQ]eELL.Bdl.B.L.LV.L.L!LMMMce	 > 
 

 r7   c                .    |                      d          S r   r   rB   s    r5   r   zColumn.__str__:  r   r7   r   )
r   r-   r   r   r   r   r   r   r.   r/   rh   rL   )rM   rN   rO   __doc__r6   r   r\   r   rQ   r7   r5   r   r     s        
 #' $%)
j 
j 
j 
j 
j      , , , , , ,r7   r   list[Column]c                     g }| D ]m}t          |t                    r1t          |          dk    rt          |d         |d                   }nt          |          }|                    |           n|S )z
    Shortcut to create many columns. If `names` param is a tuple, the first
    position will refer to the `name` while the second will be its `type`.
    Any other data structure will be treated as a whole as the `name`.
    r   r   r   r   r   )r   )ra   r   r   r   r   )r   columnsr:   columns       r5   make_columnsr   >  s~     G  dE"" 	.s4yyA~~QT!WEEEFF---FvNr7   c                      e Zd ZddZddZdS )	PeriodForr:   r-   start_columnstr | Column
end_columnr.   r/   c                    || _         t          |t                    r|nt          |          | _        t          |t                    r|nt          |          | _        d S r1   )r:   ra   r   r   r   r4   r:   r   r   s       r5   r6   zPeriodFor.__init__P  sU    	,6|V,L,LfLLRXYeRfRf(2:v(F(F^**FS]L^L^r7   rY   r   c           	         |                     d          }d                    t          | j        |           | j        j        di | | j        j        di |          }|S )Nr   z9PERIOD FOR {name} ({start_column_name},{end_column_name}))r:   start_column_nameend_column_namerQ   )r   r   r"   r:   r   r   r   )r4   rY   r   period_for_sqls       r5   r\   zPeriodFor.get_sqlU  sv    ZZ--
T[[ty*55<d/<FFvFF8DO8BB6BB \ 
 
 r7   N)r:   r-   r   r   r   r   r.   r/   rh   )rM   rN   rO   r6   r\   rQ   r7   r5   r   r   O  s@        _ _ _ _
	 	 	 	 	 	r7   r   c                  z   e Zd ZdZed-d            Zed.d	            Zed/d            Zed0d            Zed1d            Z	ed2d            Z
ed3d            Zed4d            Zed5d            Zed6d            Zed7d             Zed8d#            Zed9d$            Zed:d'            Zed;d+            Zd,S )<r   ai  
    Query is the primary class and entry point in pypika. It is used to build queries iteratively using the builder
    design
    pattern.

    This class is immutable.

    Examples
    --------
    Simple query

    .. code-block:: python

        from pypika import Query, Field
        q = Query.from_('customers').select('*').where(Field("id") == 1)
    rY   r   r.   r(   c                    t          di |S r[   )r(   )clsrY   s     r5   _builderzQuery._builderw  s    %%f%%%r7   r=   Selectable | strc                B     | j         di |                    |          S )aH  
        Query builder entry point.  Initializes query building and sets the table to select from.  When using this
        function, the query becomes a SELECT query.

        :param table:
            Type: Table or str

            An instance of a Table object or a string table name.

        :return: QueryBuilder
        rQ   )r   r   r   r=   rY   s      r5   r   zQuery.from_{  s*     s|%%f%%++E222r7   str | TableCreateQueryBuilderc                D    t                                          |          S )a(  
        Query builder entry point. Initializes query building and sets the table name to be created. When using this
        function, the query becomes a CREATE statement.

        :param table: An instance of a Table object or a string table name.

        :return: CreateQueryBuilder
        )r   create_tabler   r=   s     r5   r  zQuery.create_table  s     "##00777r7   indexstr | IndexCreateIndexBuilderc                D    t                                          |          S )z
        Query builder entry point. Initializes query building and sets the index name to be created. When using this
        function, the query becomes a CREATE statement.
        )r  create_indexr   r  s     r5   r  zQuery.create_index  s     "##00777r7   databaseDatabase | TableDropQueryBuilderc                D    t                                          |          S )a-  
        Query builder entry point. Initializes query building and sets the table name to be dropped. When using this
        function, the query becomes a DROP statement.

        :param database: An instance of a Database object or a string database name.

        :return: DropQueryBuilder
        )r  drop_database)r   r
  s     r5   r  zQuery.drop_database  s      !!//999r7   c                D    t                                          |          S )a$  
        Query builder entry point. Initializes query building and sets the table name to be dropped. When using this
        function, the query becomes a DROP statement.

        :param table: An instance of a Table object or a string table name.

        :return: DropQueryBuilder
        )r  
drop_tabler  s     r5   r  zQuery.drop_table  s      !!,,U333r7   userr-   c                D    t                                          |          S )z
        Query builder entry point. Initializes query building and sets the table name to be dropped. When using this
        function, the query becomes a DROP statement.

        :param user: String user name.

        :return: DropQueryBuilder
        )r  	drop_user)r   r  s     r5   r  zQuery.drop_user        !!++D111r7   viewc                D    t                                          |          S )z
        Query builder entry point. Initializes query building and sets the table name to be dropped. When using this
        function, the query becomes a DROP statement.

        :param view: String view name.

        :return: DropQueryBuilder
        )r  	drop_view)r   r  s     r5   r  zQuery.drop_view  r  r7   c                D    t                                          |          S )z
        Query builder entry point. Initializes query building and sets the index name to be dropped. When using this
        function, the query becomes a DROP statement.
        )r  
drop_indexr	  s     r5   r  zQuery.drop_index  s      !!,,U333r7   Table | strc                B     | j         di |                    |          S )aH  
        Query builder entry point.  Initializes query building and sets the table to insert into.  When using this
        function, the query becomes an INSERT query.

        :param table:
            Type: Table or str

            An instance of a Table object or a string table name.

        :return QueryBuilder
        rQ   )r   r   r   s      r5   r   z
Query.into  s*     s|%%f%%**5111r7   str | Selectabler:   c                D     | j         di |                    ||          S r[   )r   with_)r   r=   r:   rY   s       r5   r  zQuery.with_  s*    s|%%f%%++E4888r7   r   int | float | str | bool | Termc                ,      | j         di |j        | S )a  
        Query builder entry point.  Initializes query building without a table and selects fields.  Useful when testing
        SQL functions.

        :param terms:
            Type: list[expression]

            A list of terms to select.  These can be any type of int, float, str, bool, or Term.  They cannot be a Field
            unless the function ``Query.from_`` is called first.

        :return: QueryBuilder
        rQ   )r   r   )r   r   rY   s      r5   r   zQuery.select  s&     -|s|%%f%%,e44r7   c                B     | j         di |                    |          S )aD  
        Query builder entry point.  Initializes query building and sets the table to update.  When using this
        function, the query becomes an UPDATE query.

        :param table:
            Type: Table or str

            An instance of a Table object or a string table name.

        :return: QueryBuilder
        rQ   )r   r   r   s      r5   r   zQuery.update  s*     s|%%f%%,,U333r7   
table_name_TableClassc                &    | |d<   t          |fi |S )z
        Convenience method for creating a Table that uses this Query class.

        :param table_name:
            Type: str

            A string table name.

        :return: Table
        r   r}   )r   r"  rY   s      r5   ry   zQuery.Table  s$     "{Z**6***r7   r   r   list[_TableClass]c                $    | |d<   t          |i |S )a!  
        Convenience method for creating many tables that uses this Query class.
        See ``Query.make_tables`` for details.

        :param names:
            Type: list[str or tuple]

            A list of string table names, or name and alias tuples.

        :return: Table
        r   )r   )r   r   rY   s      r5   TableszQuery.Tables  s!     "{E,V,,,r7   N)rY   r   r.   r(   )r=   r   rY   r   r.   r(   )r=   r   r.   r   )r  r  r.   r  )r
  r  r.   r  )r=   r   r.   r  )r  r-   r.   r  )r  r-   r.   r  )r  r  r.   r  )r=   r  rY   r   r.   r(   )r=   r  r:   r-   rY   r   r.   r(   )r   r  rY   r   r.   r(   )r=   r   r.   r(   )r"  r-   r.   r#  )r   r   rY   r   r.   r%  )rM   rN   rO   r   classmethodr   r   r  r  r  r  r  r  r  r   r  r   r   ry   r'  rQ   r7   r5   r   r   e  s        " & & & [& 3 3 3 [3 	8 	8 	8 [	8 8 8 8 [8 	: 	: 	: [	: 	4 	4 	4 [	4 	2 	2 	2 [	2 	2 	2 	2 [	2 4 4 4 [4 2 2 2 [2 9 9 9 [9 5 5 5 [5 4 4 4 [4 + + + [+ - - - [- - -r7   r   c                  .    e Zd ZdZdefd. fdZed/d            Zed0d            Zed1d            Z	ed2d            Z
ed2d            Zed2d            Zed2d            Zed2d            Zd3d Zd3d!Zd4d"Zd5d$Zd6d7d)Zd8d9d+Zd5d,Zd5d-Z xZS ):_SetOperationa  
    A Query class wrapper for a all set operations, Union DISTINCT or ALL, Intersect, Except or Minus

    Created via the functions `Query.union`,`Query.union_all`,`Query.intersect`, `Query.except_of`,`Query.minus`.

    This class should not be instantiated directly.
    N
base_queryr(   set_operation_queryset_operationr   r,   r   wrapper_clstype[ValueWrapper]c                    t                                          |           || _        ||fg| _        g | _        d | _        d | _        || _        d S r1   )rW   r6   r+  _set_operation	_orderbys_limit_offset_wrapper_cls)r4   r+  r,  r-  r,   r.  rX   s         r5   r6   z_SetOperation.__init__1  sX     	$ -/BCD'r7   fieldsr   rY   r   r.   r/   c                   |D ]}t          |t                    r!t          || j        j        d                   n| j                            |          }| j                            ||                    d          f           d S Nr   r<   order)	ra   r-   r   r+  _fromwrap_constantr2  r   r   r4   r6  rY   r@   s       r5   orderbyz_SetOperation.orderbyC  s     	@ 	@E eS)):e4?#8#;<<<<_22599  N!!5&**W*=*=">????	@ 	@r7   limitrd   c                    || _         d S r1   r3  r4   r>  s     r5   r>  z_SetOperation.limitN      r7   offsetc                    || _         d S r1   r4  r4   rC  s     r5   rC  z_SetOperation.offsetR      r7   r^   r+   c                R    | j                             t          j        |f           d S r1   )r1  r   r   unionrb   s     r5   rI  z_SetOperation.unionV  '    ""L$6#>?????r7   c                R    | j                             t          j        |f           d S r1   )r1  r   r   	union_allrb   s     r5   rL  z_SetOperation.union_allZ  '    ""L$:E#BCCCCCr7   c                R    | j                             t          j        |f           d S r1   )r1  r   r   	intersectrb   s     r5   rO  z_SetOperation.intersect^  rM  r7   c                R    | j                             t          j        |f           d S r1   )r1  r   r   	except_ofrb   s     r5   rQ  z_SetOperation.except_ofb  rM  r7   c                R    | j                             t          j        |f           d S r1   )r1  r   r   minusrb   s     r5   rS  z_SetOperation.minusf  rJ  r7   c                ,    |                      |          S r1   rI  rb   s     r5   __add__z_SetOperation.__add__j      zz%   r7   c                ,    |                      |          S r1   rL  rb   s     r5   __mul__z_SetOperation.__mul__m      ~~e$$$r7   c                ,    |                      |          S r1   rS  rb   s     r5   __sub__z_SetOperation.__sub__p  rW  r7   r-   c                *    |                                  S r1   r   rB   s    r5   r   z_SetOperation.__str__s      ||~~r7   F
with_aliasr_   subqueryc                   d}|                     d| j        j                   |                     d| j        j                    | j        j        d
d| j        j        i|}|}| j        D ]\  }} |j        d
d| j        j        i|}	t          | j        j                  t          |j                  k    r$t          d
                    ||	                    ||
                    |j        |	          z  }| j        r| | j        d
i |z  }| j        ||                                 z  }| j        r||                                 z  }|r dj
        d
d	|i|}|rt%          || j        p| j        fi |S |S )Nz {type} {query_string}dialectr   rb  zQueries must have an equal number of select statements in a set operation.

Main Query:
{query1}

Set Operations Query:
{query2})query1query2)r   query_string	({query})rT   rQ   )
setdefaultr+  rd  
QUOTE_CHARr\   wrap_set_operation_queriesr1  r   _selectsr   r   valuer2  _orderby_sqlr3  
_limit_sqlr4  _offset_sqlr!   r,   r   )
r4   ra  rb  rY   set_operation_templatebase_querystringquerystringr-  r,  set_operation_querystrings
             r5   r\   z_SetOperation.get_sqlv  s   !9)T_%<=== 	,(BCCC24?2qqDO<fqjpqq&262E 	 	.M.(C(;(C ) )C)GM) )% 4?+,,4G4P0Q0QQQ+SSYSY/8Q TZ T T   188"(7P 9   KK > 	7,4,66v666K;"4??,,,K< 	.4++---K 	J,+,II;I&IIK 	[#K1Ot?OZZSYZZZr7   r   c                l   g }d | j         j        D             }| j        D ]l\  }}|j        r|j        |v rt	          |j        |          n |j        d	d|i|}|                    |d                    ||j                  n|           md                    d	                    |                    S )
a  
        Produces the ORDER BY part of the query.  This is a list of fields and possibly their directionality, ASC or
        DESC. The clauses are stored in the query under self._orderbys as a list of tuples containing the field and
        directionality (which can be None).

        If an order by field is used in the select clause, determined by a matching , then the ORDER BY clause will use
        the alias, otherwise the field will be rendered as SQL.
        c                    h | ]	}|j         
S rQ   r2   .0r   s     r5   	<setcomp>z-_SetOperation._orderby_sql.<locals>.<setcomp>  s    FFFAGFFFr7   r   N{term} {orient}termorient ORDER BY {orderby},r=  rQ   )
r+  rl  r2  r,   r"   r\   r   r   rm  join)r4   r   rY   clausesselected_aliasesr@   directionalityr|  s           r5   rn  z_SetOperation._orderby_sql  s     FFT_-EFFF%)^ 		 		!E> ;D#(;2B#B#B ek:666"U]CCjCFCC  NNTbTn!((d>;O(PPPtx    %++CHHW4E4E+FFFr7   c                8    d                     | j                  S )Nz OFFSET {offset})rC  )r   r4  rB   s    r5   rp  z_SetOperation._offset_sql  s    !(((===r7   c                8    d                     | j                  S )Nz LIMIT {limit})r>  )r   r3  rB   s    r5   ro  z_SetOperation._limit_sql  s    &&T[&999r7   )
r+  r(   r,  r(   r-  r   r,   r   r.  r/  )r6  r   rY   r   r.   r/   r>  rd   r.   r/   rC  rd   r.   r/   )r^   r+   r.   r/   )r^   r+   r.   r*  r^   r(   r.   r*  rL   FFra  r_   rb  r_   rY   r   r.   r-   r1   r   )rM   rN   rO   r   r   r6   r    r=  r>  rC  rI  rL  rO  rQ  rS  rV  rZ  r^  r   r\   rn  rp  ro  rj   rk   s   @r5   r*  r*  (  s         !*6( ( ( ( ( ( ($ @ @ @ W@    W    W @ @ @ W@ D D D WD D D D WD D D D WD @ @ @ W@! ! ! !% % % %! ! ! !   + + + + +ZG G G G G0> > > >: : : : : : : :r7   r*  c                  ~    e Zd ZdZdZdZdZdZeZ	dde
ddfd fdZddZedd            Zedd            Zedd            Zedd             Zedd#            Zedd$            Zedd%            Zedd&            Zedd'            Zedd(            Zedd+            Zedd,            Zedd-            Zedd.            Zedd/            Zedd2            Zedd4            Zedd5            Zedd6            Z edd8            Z!edd9            Z"edd<            Z#edd>            Z$ee%j&        fddD            Z'ddFZ(ddGZ)ddHZ*ddIZ+ddJZ,ddKZ-ddLZ.ddMZ/ddNZ0eddQ            Z1eddS            Z2eddV            Z3eddW            Z4eddX            Z5eddY            Z6eddZ            Z7edd^            Z8dd_Z9dd`Z:ddaZ;eddc            Z<d fdeZ=e>dddk            Z?ddlZ@ddnZAddqZBddsZCddvZDddxZEddzZFdd|ZGdd}ZHdd~ZIddZJddZKddZLddZMddZNdddZOddZPddZQddZRddZSddZTddZUddZVe>dd            ZWddZXdddZYddZZddZ[dddZ\dddZ]ddZ^ddZ_dddZ`dddZa	 	 	 dddZb	 	 	 dddZcddZddddZedddZfddZgddZhddZid Zj xZkS )r(   z
    Query Builder is the main class in pypika which stores the state of a query and offers functions which allow the
    state to be branched immutably.
    r   'NTFrd  Dialects | Nonerk  r_   r.  r/  	immutable
as_keywordc                v   t                                          d            g | _        d | _        d | _        d| _        d| _        g | _        g | _        g | _	        g | _
        g | _        g | _        d| _        d| _        d| _        d | _        d | _        g | _        d| _        d | _        d | _        g | _        g | _        g | _        g | _        d | _        d | _        g | _        d| _        t=                      | _        d| _         d| _!        d| _"        d| _#        || _$        || _%        || _&        || _'        || _(        d S )NFr   ))rW   r6   r:  _insert_table_update_table_delete_from_replace_withrl  _force_indexes_use_indexes_columns_values	_distinct_ignore_for_update_wheres
_prewheres	_groupbys_with_totals_havings	_qualifysr2  _joins_unions_usingr3  r4  _updates_select_starset_select_star_tables_mysql_rollup_select_into_subquery_count_foreign_tablerd  r  rk  r5  r  )r4   rd  rk  r.  r  r  rX   s         r5   r6   zQueryBuilder.__init__  s>    	
!!!
  !!#&55 "! #$*D''"r7   r.   c                ,   t          |                               t          |                     }|j                            | j                   t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        t	          | j	                  |_	        t	          | j
                  |_
        t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        t	          | j                  |_        |S r1   )r   __new____dict__r   r   r  r:  r  rl  r  r  r  r2  r  r  r  r  r  )r4   newones     r5   __copy__zQueryBuilder.__copy__	  s#   d##DJJ//t}---%)$*B%C%C"DJ''DJ''t}--t}--dl++////T[))dl++t}-- $T%8 9 9"4#455r7   
selectableSelectable | Query | strr/   c                `   | j                             t          |t                    rt	          |          n|           t          |t
          t          f          rQ|j        Lt          |t
                    r|j        }nd}t          | j        |          }d|z  |_        |dz   | _        dS dS dS )a  
        Adds a table to the query. This function can only be called once and will raise an AttributeError if called a
        second time.

        :param selectable:
            Type: ``Table``, ``Query``, or ``str``

            When a ``str`` is passed, a table with the name matching the ``str`` value is used.

        :returns
            A copy of the query with the table added.
        Nr   sq%dr   )
r:  r   ra   r-   ry   r(   r*  r,   r  max)r4   r  sub_query_counts      r5   r   zQueryBuilder.from_  s     	
z*c/J/JZ%
+++PZ[[[j<"?@@ 	7ZEUE]*l33 $","<"#!$"6HHO%7J#2Q#6D   	7 	7E]E]r7   current_tableTable | None	new_tablec                   fd| j         D             | _         | j        k    rn| j        | _        | j        k    rn| j        | _        fd| j        D             | _        fd| j        D             | _        fd| j        D             | _        fd| j        D             | _        | j        r| j                                      nd| _        | j	        r| j	                                      nd| _	        fd| j
        D             | _
        | j        r| j                                      nd| _        | j        r| j                                      nd| _        fd| j        D             | _        fd	| j        D             | _        | j        v r6| j                                       | j                                       dS dS )
ak  
        Replaces all occurrences of the specified table with the new table. Useful when reusing fields across
        queries.

        :param current_table:
            The table instance to be replaces.
        :param new_table:
            The table instance to replace with.
        :return:
            A copy of the query with the tables replaced.
        c                $    g | ]}|k    rn|S rQ   rQ   )rx  r=   r  r  s     r5   
<listcomp>z.QueryBuilder.replace_table.<locals>.<listcomp>C  s'    ]]]5M#9#9iiu]]]r7   c                <    g | ]}|                               S rQ   replace_table)rx  alias_queryr  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>G  s)    hhhkk//yIIhhhr7   c                <    g | ]}|                               S rQ   r  )rx  r   r  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>H  )    dddF--mYGGdddr7   c                <    g | ]}|                               S rQ   r  )rx  r   r  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>I  r  r7   c                .    g | ]}fd |D             S )c                <    g | ]}|                               S rQ   r  )rx  rm  r  r  s     r5   r  z9QueryBuilder.replace_table.<locals>.<listcomp>.<listcomp>K  s)    SSSuU  	::SSSr7   rQ   )rx  
value_listr  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>J  s>     
 
 
XbSSSSS
SSS
 
 
r7   Nc                <    g | ]}|                               S rQ   r  )rx  groupbyr  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>P  s)    hhhg'//yIIhhhr7   c                X    g | ]&}|d                                         |d         f'S )r   r   r  )rx  r=  r  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>S  sC     
 
 
QXWQZ%%mY??L
 
 
r7   c                <    g | ]}|                               S rQ   r  )rx  r  r  r  s     r5   r  z.QueryBuilder.replace_table.<locals>.<listcomp>V  s)    \\\t))-CC\\\r7   )r:  r  r  r  rl  r  r  r  r  r  r  r  r  r2  r  r  removeaddr4   r  r  s    ``r5   r  zQueryBuilder.replace_table6  s]    ^]]]]RVR\]]]
*.*<*M*MYYSWSe*.*<*M*MYYSWSehhhhh]a]ghhh
dddddVZVcddddddddVZVcddd
 
 
 
 
fjfr
 
 
 PT|et|11-KKKaeUYUdn$/77yQQQjnhhhhhY]YghhhQUQ^h33M9MMMdhSWSak55mYOOOgk
 
 
 
 
\`\j
 
 
 ]\\\\PTP[\\\D444$++M:::$((33333 54r7   r+   r:   r-   c                Z    t          ||          }| j                            |           d S r1   )rS   r  r   )r4   r  r:   r   s       r5   r  zQueryBuilder.with_\  s-    z**
!r7   r=   r   c                    | j         t          ddz            | j        rd| _        t	          |t
                    r|nt          |          | _         d S )N$'Query' object has no attribute '%s'r   T)r  r   rl  r  ra   ry   r4   r=   s     r5   r   zQueryBuilder.intoa  sX    ) !G&!PQQQ= 	% $D&0&>&>PUUE%LLr7   r   r   c                ~   |D ]}t          |t                    r|                     |           -t          |t                    r|                     |           Xt          |t
          t          f          r|                     |           |                     |                     || j	                             d S N)r.  )
ra   r   _select_fieldr-   _select_field_strr   r   _select_otherr;  r5  r4   r   r|  s      r5   r   zQueryBuilder.selectk  s     	\ 	\D$&& \""4((((D#&& \&&t,,,,D8-A"BCC \""4((((""4#5#5dHY#5#Z#Z[[[[	\ 	\r7   c                b    | j         s| j        s| j        rt          ddz            d| _         d S )Nr  deleteT)r  rl  r  r   rB   s    r5   r  zQueryBuilder.deletew  sE     	T 	T1C 	T !G(!RSSS r7   c                    | j         | j        s| j        rt          ddz            t	          |t
                    r|nt          |          | _         d S )Nr  r   )r  rl  r  r   ra   ry   r  s     r5   r   zQueryBuilder.update~  sU    )T])d>O) !G(!RSSS&0&>&>PUUE%LLr7   c                $   | j         t          ddz            |r*t          |d         t          t          f          r|d         }|D ]G}t          |t
                    rt          || j                   }| j                            |           Hd S )Nr  r   r   r<   )	r  r   ra   r   r   r-   r   r  r   r  s      r5   r   zQueryBuilder.columns  s    % !G(!RSSS 	Za4-88 	!HE 	' 	'D$$$ =T);<<<M  &&&&	' 	'r7   c                (     | j         |  d| _        d S NF_apply_termsr  r   s     r5   r   zQueryBuilder.insert  s    5!!r7   c                (     | j         |  d| _        d S NTr  r   s     r5   replacezQueryBuilder.replace  s    5!!r7   r|  r  c                    |g|R D ]n}t          |t                    r| j                            |           2t          |t                    r'| j                            t          |                     od S r1   )ra   r   r  r   r-   r4   r|  r   r   s       r5   force_indexzQueryBuilder.force_index  s     	5 	5A!U## 5#**1----As## 5#**588444		5 	5r7   c                    |g|R D ]n}t          |t                    r| j                            |           2t          |t                    r'| j                            t          |                     od S r1   )ra   r   r  r   r-   r  s       r5   	use_indexzQueryBuilder.use_index  s     	3 	3A!U## 3!((++++As## 3!((q222		3 	3r7   c                    d| _         d S r  r  rB   s    r5   distinctzQueryBuilder.distinct  s    r7   c                    d| _         d S r  r  rB   s    r5   
for_updatezQueryBuilder.for_update  s    r7   c                    d| _         d S r  )r  rB   s    r5   ignorezQueryBuilder.ignore  s    r7   r   r   c                ~    |                      |          sd| _        | j        r| xj        |z  c_        d S || _        d S r  )_validate_tabler  r  r4   r   s     r5   prewherezQueryBuilder.prewhere  sI    ##I.. 	'"&D? 	(OOy(OOOO'DOOOr7   Term | EmptyCriterionc                    t          |t                    rd S |                     |          sd| _        | j        r| xj        |z  c_        d S || _        d S r  )ra   r   r  r  r  r  s     r5   wherezQueryBuilder.where  s`    i00 	F##I.. 	'"&D< 	%LLI%LLLL$DLLLr7   c                t    t          |t                    rd S | j        r| xj        |z  c_        d S || _        d S r1   )ra   r   r  r  s     r5   havingzQueryBuilder.having  sB    i00 	F= 	&MMY&MMMM%DMMMr7   c                t    t          |t                    rd S | j        r| xj        |z  c_        d S || _        d S r1   )ra   r   r  r  s     r5   qualifyzQueryBuilder.qualify  sB    i00 	F> 	'NNi'NNNN&DNNNr7   str | int | Termc                J   |D ]}t          |t                    rt          || j        d                   }nQt          |t                    r<t          t          |          | j        d                                       |          }| j                            |           d S )Nr   r<   )ra   r-   r   r:  rd   r;  r  r   r  s      r5   r  zQueryBuilder.groupby  s     	( 	(D$$$ QTA777D#&& QSYYdjm<<<JJ4PPN!!$''''	( 	(r7   c                    d| _         d S r  )r  rB   s    r5   with_totalszQueryBuilder.with_totals  s     r7   list | tuple | set | TermrY   c                   d|                     d          k    }| j        rt          ddz            d |D             }|r1|s| j        st	          d          d| _        | xj        |z  c_        d S dt          | j                  k     r=t          | j        d	         t                    r| j        d	         xj        |z  c_        d S | j        	                    t          |            d S )
Nmysqlvendorr  rollupc                h    g | ]/}t          |t          t          t          f          r	t	          | n|0S rQ   )ra   r   r   r  r   )rx  r|  s     r5   r  z'QueryBuilder.rollup.<locals>.<listcomp>  s7    bbbTXD42D!E!EO4bbbr7   zWAt least one group is required. Call Query.groupby(term) or passas parameter to rollup.Tr   )
r   r  r   r  r   r   ra   r   argsr   )r4   r   rY   	for_mysqls       r5   r  zQueryBuilder.rollup  s   vzz(333	 	T !G(!RSSSbb\abbb 	2  %p   "&DNNe#NNNNT^$$$$DN24F)O)O$N2##u,#### N!!&%.11111r7   r6  c                    |D ]w}t          |t                    rt          || j        d                   n|                     |          }| j                            ||                    d          f           xd S r8  )ra   r-   r   r:  r;  r2  r   r   r<  s       r5   r=  zQueryBuilder.orderby  s     	@ 	@E9CE39O9OnE%tz!}5555UYUgUghmUnUnEN!!5&**W*=*=">????	@ 	@r7   rx   0Table | QueryBuilder | AliasedQuery | Selectablehowr   Joiner[Self]c                   t          |t                    rt          | ||d          S t          |t                    r/|j        |                     |           t          | ||d          S t          |t                    rt          | ||d          S t          |t                    rt          | ||d          S t          dt          |          z            )Nr=   )
type_labelrb  zCannot join on type '%s')
ra   ry   Joinerr(   r,   _tag_subqueryrS   r+   
ValueErrorr   r4   rx   r  s      r5   r  zQueryBuilder.join  s     dE"" 	B$cg>>>>l++ 		Bz!""4((($cjAAAAl++ 	B$cg>>>>j)) 	B$cjAAAA3d4jj@AAAr7   #Table | QueryBuilder | AliasedQueryc                B    |                      |t          j                  S r1   )r  r   innerr~   s     r5   
inner_joinzQueryBuilder.inner_join&      yyx~...r7   c                B    |                      |t          j                  S r1   )r  r   leftr~   s     r5   	left_joinzQueryBuilder.left_join)      yyx}---r7   c                B    |                      |t          j                  S r1   )r  r   
left_outerr~   s     r5   left_outer_joinzQueryBuilder.left_outer_join,      yyx2333r7   c                B    |                      |t          j                  S r1   )r  r   rightr~   s     r5   
right_joinzQueryBuilder.right_join/  r  r7   c                B    |                      |t          j                  S r1   )r  r   right_outerr~   s     r5   right_outer_joinzQueryBuilder.right_outer_join2  s    yyx3444r7   c                B    |                      |t          j                  S r1   )r  r   outerr~   s     r5   
outer_joinzQueryBuilder.outer_join5  r  r7   c                B    |                      |t          j                  S r1   )r  r   
full_outerr~   s     r5   full_outer_joinzQueryBuilder.full_outer_join8  r!  r7   c                B    |                      |t          j                  S r1   )r  r   crossr~   s     r5   
cross_joinzQueryBuilder.cross_join;  r  r7   c                B    |                      |t          j                  S r1   )r  r   rf   r~   s     r5   	hash_joinzQueryBuilder.hash_join>  r  r7   r>  rd   c                    || _         d S r1   r@  rA  s     r5   r>  zQueryBuilder.limitA  rB  r7   rC  c                    || _         d S r1   rE  rF  s     r5   rC  zQueryBuilder.offsetE  rG  r7   r^   r*  c                F    t          | |t          j        | j                  S r  )r*  r   rI  r5  rb   s     r5   rI  zQueryBuilder.unionI      T5,*<$J[\\\\r7   c                F    t          | |t          j        | j                  S r  )r*  r   rL  r5  rb   s     r5   rL  zQueryBuilder.union_allM      T5,*@dN_````r7   c                F    t          | |t          j        | j                  S r  )r*  r   rO  r5  rb   s     r5   rO  zQueryBuilder.intersectQ  r8  r7   c                F    t          | |t          j        | j                  S r  )r*  r   rQ  r5  rb   s     r5   rQ  zQueryBuilder.except_ofU  r8  r7   c                F    t          | |t          j        | j                  S r  )r*  r   rS  r5  rb   s     r5   rS  zQueryBuilder.minusY  r6  r7   r@   Field | strrm  c                    t          |t                    st          |          n|}t          |t                    s|                     || j                  }| j                            ||f           d S r  )ra   r   r   r;  r5  r  r   )r4   r@   rm  s      r5   r  zQueryBuilder.set]  sn    $.ue$<$<Ge%%&& 	M&&u$:K&LLEeU^,,,,,r7   c                ,    |                      |          S r1   rU  rb   s     r5   rV  zQueryBuilder.__add__d  rW  r7   c                ,    |                      |          S r1   rY  rb   s     r5   rZ  zQueryBuilder.__mul__g  r[  r7   c                ,    |                      |          S r1   r]  rb   s     r5   r^  zQueryBuilder.__sub__j  rW  r7   slicec                6    |j         | _        |j        | _        d S r1   )startr4  stopr3  )r4   rA  s     r5   rA  zQueryBuilder.slicem  s    {jr7   QueryBuilder | Fieldc                    t          |t                    s!t                                          |          S |                     |          S r1   )ra   rA  rW   rI   )r4   rx   rX   s     r5   rI   zQueryBuilder.__getitem__r  s?    $&& 	-77&&t,,,zz$r7   	field_setSequence[Field]r   r   	list[str]c                     fd| D             S )Nc                J    g | ]}|j         p|                                S )r   )r,   r\   )rx  r@   r   s     r5   r  z.QueryBuilder._list_aliases.<locals>.<listcomp>y  s.    [[[Cu}}
}CC[[[r7   rQ   )rG  r   s    `r5   _list_aliaseszQueryBuilder._list_aliasesw  s    [[[[QZ[[[[r7   c                    dt          | j                  k    rt          d| d          |dk    rd| _        t	                      g| _        d S |                     t          || j        d                              d S )Nr   zCannot select z, no FROM table specified.*Tr<   )r   r:  r   r  r   rl  r  r   r4   r|  s     r5   r  zQueryBuilder._select_field_str{  s    DJ !R$!R!R!RSSS3;; $D!VVHDMF5TZ];;;<<<<<r7   r   c                   | j         rd S j        | j        v rd S t          t                    r7fd| j        D             | _        | j                            j                   | j                                       d S )Nc                T    g | ]$}t          |d           rj        |j        k    "|%S r<   )hasattrr=   )rx  r   r|  s     r5   r  z.QueryBuilder._select_field.<locals>.<listcomp>  sC       !'&':R:RVZV`djdpVpVpVpVpVpr7   )r  r=   r  ra   r   rl  r  r   rO  s    `r5   r  zQueryBuilder._select_field  s     	F:111FdD!! 	5   %)]  DM $((444T"""""r7   functionr   c                :    | j                             |           d S r1   )rl  r   )r4   rS  s     r5   r  zQueryBuilder._select_other  s    X&&&&&r7   list[Field]c                    g S r1   rQ   rB   s    r5   fields_zQueryBuilder.fields_  s    	r7   r  Joinc                ^   | j         | j        gz   | j        z                       | j                   t          fdD                       }t          j        t                    r'j        j	        |rj        j
        dz   j        _	        | j                                       d S )Nc              3  T   K   | ]"}t          |t                    oj        v V  #d S r1   )ra   ry   rx   )rx  clausebase_tablesr  s     r5   	<genexpr>z'QueryBuilder.do_join.<locals>.<genexpr>  s:      nnX^Z66S49;Snnnnnnr7   2)r:  r  r  validater  anyra   rx   ry   r,   r   r   )r4   r  table_in_queryr\  s    ` @r5   do_joinzQueryBuilder.do_join  s    jD$6#77$*Dk4;///nnnnnbmnnnnndi'' 	:DIO,C,C #i3c9DIO4     r7   ry   c                D    t          fd| j        D                       S )Nc              3  .   K   | ]}|j         k    V  d S r1   rx   )rx  r  r=   s     r5   r]  z)QueryBuilder.is_joined.<locals>.<genexpr>  s*      >>$5DI%>>>>>>r7   )r`  r  r  s    `r5   	is_joinedzQueryBuilder.is_joined  s(    >>>>$+>>>>>>r7   r   c                    | j         | j        gz   }|                                D ]P}|j        |v }|j        d | j        D             v }t          |j        du| | |j        | j        k    g          r dS QdS )z
        Returns False if the term references a table not already part of the
        FROM clause or JOINS and True otherwise.
        c                    g | ]	}|j         
S rQ   re  rx  r  s     r5   r  z0QueryBuilder._validate_table.<locals>.<listcomp>  s    ,O,O,O4TY,O,O,Or7   NFT)r:  r  rW  r=   r  all)r4   r|  r\  r@   table_in_base_tablestable_in_joinss         r5   r  zQueryBuilder._validate_table  s    
 jD$6#77\\^^ 	 	E#(;+#= "[,O,O4;,O,O,OONKt+,,&&K4#55	   uu tr7   rb  c                D    d| j         z  |_        | xj         dz  c_         d S )Nr  r   )r  r,   )r4   rb  s     r5   r  zQueryBuilder._tag_subquery  s+    $"66!r7   c                      j         t          ddz            |sdS t          |d         t          t          t
          f          s|g}|D ](} j                             fd|D                        )dS )z
        Handy function for INSERT and REPLACE statements in order to check if
        terms are introduced and how append them to `self._values`
        Nr  r   r   c                h    g | ].}t          |t                    r|n                    |          /S rQ   )ra   r   r;  )rx  rm  r4   s     r5   r  z-QueryBuilder._apply_terms.<locals>.<listcomp>  s<     u u uej*UD*A*A!`tGYGYZ_G`G` u u ur7   )r  r   ra   r   r   r  r  r   )r4   r   valuess   `  r5   r  zQueryBuilder._apply_terms  s    
 % !G(!RSSS 	F%(T5#$677 	GE 	w 	wFL u u u unt u u uvvvv	w 	wr7   c                8    |                      | j                  S )N)rd  )r\   rd  rB   s    r5   r   zQueryBuilder.__str__  s    ||DL|111r7   c                *    |                                  S r1   r   rB   s    r5   r   zQueryBuilder.__repr__  r`  r7   c                X    t          |t                    sdS | j        |j        k    sdS dS r   )ra   r(   r,   rb   s     r5   rc   zQueryBuilder.__eq__  s2    %.. 	5zU[((5tr7   c                .    |                      |           S r1   ru   rb   s     r5   rv   zQueryBuilder.__ne__  rw   r7   c                h    t          | j                  t          d | j        D                       z   S )Nc              3  4   K   | ]}t          |          V  d S r1   )rf   )rx  r[  s     r5   r]  z(QueryBuilder.__hash__.<locals>.<genexpr>  s(      %L%Lvd6ll%L%L%L%L%L%Lr7   )rf   r,   sumr:  rB   s    r5   rg   zQueryBuilder.__hash__  s0    DJ#%L%L%L%L%L"L"LLLr7   dictc                   |                     d| j                   |                     d| j                   |                     d| j                   |                     d| j                   |                     d| j                   d S )Nr   secondary_quote_charalias_quote_charr  rd  )ri  rj  SECONDARY_QUOTE_CHARALIAS_QUOTE_CHARr  rd  r]   s     r5   _set_kwargs_defaultsz!QueryBuilder._set_kwargs_defaults  s    ,8880$2KLLL,d.CDDD,888)T\22222r7   ra  c                ^   |                                 | j        s| j        s| j        s	| j        sdS | j        r| j        s	| j        sdS | j        r	| j        sdS t          | j                  }dt          | j
                  k     }dt          | j
                  k     ot          | j
        d         t                    }| j        }| j        o| j
        }t          |||||g          d<   | j        r| j        r | j        di nd}	|	 | j        di z  }	| j        r,|	dd                    fd| j        D                       z   z  }	|	 | j        di z  }	| j
        r|	 | j        di z  }	| j        r|	 | j        di z  }	| j        |	|                                 z  }	|	S | j        r | j        di }	n| j        s| j        r| j        r | j        di nd}	| j        r|	 | j        di z  }	n|	 | j        di z  }	| j        r|	 | j        di z  }	| j        r|	 | j         di z  }	|	S |	d | j!        di z   z  }	n=| j        r | j        di nd}	|	 | j!        di z  }	| j        r|	 | j"        di z  }	| j
        r|	 | j        di z  }	| j#        r|	 | j$        di z  }	| j%        r|	 | j&        di z  }	| j'        r|	 | j(        di z  }	| j        r,|	dd                    fd| j        D                       z   z  }	| j)        r|	 | j*        di z  }	| j        r|	 | j        di z  }	| j+        r.|	 | j,        di z  }	| j-        r|	| .                                z  }	| j/        r|	 | j0        di z  }	| j1        r|	 | j2        di z  }	| j3        r|	 | j4        di z  }	 | j5        |	fi }	| j6        r|	 | j7        di z  }	|rd8                    |		          }	|r+| j9        | j:        n| j9        d
<   tw          |	| j<        fi S |	S )Nr   r   r   with_namespace c              3  2   K   | ]} |j         di V  d S r[   r   rx  r  rY   s     r5   r]  z'QueryBuilder.get_sql.<locals>.<genexpr>  s5      -]-]ldl.D.DV.D.D-]-]-]-]-]-]r7   c              3  2   K   | ]} |j         di V  d S r[   r   r  s     r5   r]  z'QueryBuilder.get_sql.<locals>.<genexpr>J  s5      )Y)YT,$,*@*@*@*@)Y)Y)Y)Y)Y)Yr7   rh  rT   r|  rQ   )=r  rl  r  r  r  r  r  r_   r  r   r:  ra   r(   r  r`  r  	_with_sql_update_sqlr  _set_sql	_from_sqlr  
_where_sqlr3  ro  _delete_sqlr  r  _replace_sql_insert_sqlr  _columns_sql_values_sql_select_sql	_into_sqlr  
_using_sqlr  _force_index_sqlr  _use_index_sqlr  _prewhere_sqlr  
_group_sqlr  _rollup_sqlr  _having_sqlr  _qualify_sqlr2  rn  _apply_paginationr  _for_update_sqlr   QUERY_ALIAS_QUOTE_CHARr~  r!   r,   )
r4   ra  rb  rY   	has_joinshas_multiple_from_clauseshas_subquery_from_clausehas_reference_to_foreign_tablehas_update_fromrs  s
      `      r5   r\   zQueryBuilder.get_sql  sE   !!&))) 	!3 	t7H 	DL^ 	2 	t} 	 	2 	dm 	2%%	$%DJ$7!#$s4:#6#b:djQRmUa;b;b )-)<&,;#&)(.$
 $
   	6:jH.$.226222bK+4+55f555K{ ^sSXX-]-]-]-]QUQ\-]-]-]%]%]]]=4=226222Kz 8~t~77777| 9t88888{&t000 	8*$*44V44KK" 	8t'9 	86:jH.$.226222bK} :0t0::6:::/t/99&999} ;0t0::6:::| @/t/99&999""s%5T%5%?%?%?%??? 7;jH.$.226222bK+4+55f555K! 8~t~77777: 	4>4>33F333K; 	5?4?44V444K 	;040::6:::K 	9.4.88888K; 	Z3)Y)Y)Y)YT[)Y)Y)Y!Y!YYYK? 	8-4-77777K< 	5?4?44V444K> 	2?4?44V444K! 2t//111= 	6+4+55f555K> 	7,4,66v666K> 	7,4,66v666K,d,[CCFCC 	:/4/99&999K 	@%,,;,??K 	G)-)D)L%%RVRm %& $KFFvFFFr7   rs  c                ~    | j         ||                                 z  }| j        r||                                 z  }|S r1   )r3  ro  r4  rp  )r4   rs  rY   s      r5   r  zQueryBuilder._apply_paginationp  sD    ;"4??,,,K< 	.4++---Kr7   c                V    dd                     fd| j        D                       z   S )NzWITH r  c              3  T   K   | ]"}|j         d z    |j        ddddz   dz   V  #dS )z AS (Frb  ra  z) NrQ   )r:   r\   rx  r[  rY   s     r5   r]  z)QueryBuilder._with_sql.<locals>.<genexpr>z  sc       "
 "
 K'!NFN$^Ee$^$^W]$^$^^aee"
 "
 "
 "
 "
 "
r7   )r  r  r]   s    `r5   r  zQueryBuilder._with_sqly  sH     "
 "
 "
 "
*"
 "
 "
 
 
 
 	
r7   c                    | j         rdnd}|S )Nz	DISTINCT r   r  )r4   rY   r  s      r5   _distinct_sqlzQueryBuilder._distinct_sql  s    "&.8;;br7   c                    | j         rdnd}|S )Nz FOR UPDATEr   r  )r4   rY   r  s      r5   r  zQueryBuilder._for_update_sql  s    &*&6>]]B
r7   c                    d                      | j        di d                    fd| j        D                                 S )NzSELECT {distinct}{select}r  c              3  8   K   | ]} |j         dd d dV  dS T)ra  rb  NrQ   r   rx  r|  rY   s     r5   r]  z+QueryBuilder._select_sql.<locals>.<genexpr>  s=      mmW[LDLRD4RR6RRmmmmmmr7   )r  r   rQ   )r   r  r  rl  r]   s    `r5   r  zQueryBuilder._select_sql  s^    *11'T'11&1188mmmm_c_lmmmmm 2 
 
 	
r7   c                b    d                      | j        j        di || j        rdnd          S )NzINSERT {ignore}INTO {table}zIGNORE r   )r=   r  rQ   )r   r  r\   r  r]   s     r5   r  zQueryBuilder._insert_sql  sF    ,33,$$,66v66 $499" 4 
 
 	
r7   c                N    d                      | j        j        di |          S )NzREPLACE INTO {table}r<   rQ   r   r  r\   r]   s     r5   r  zQueryBuilder._replace_sql  s8    %,,,$$,66v66 - 
 
 	
r7   c                     dS )NDELETErQ   )rY   s    r5   r  zQueryBuilder._delete_sql  s    xr7   c                N    d                      | j        j        di |          S )NzUPDATE {table}r<   rQ   )r   r  r\   r]   s     r5   r  zQueryBuilder._update_sql  s0    &&-GT-?-G-Q-Q&-Q-Q&RRRr7   r  c                x    d                     d                    fd| j        D                                 S )z
        SQL for Columns clause for INSERT queries
        :param with_namespace:
            Remove from kwargs, never format the column terms with namespaces since only one table can be inserted into
        z ({columns})r  c              3  6   K   | ]} |j         dd diV  dS )r  FNrQ   r   r  s     r5   r]  z,QueryBuilder._columns_sql.<locals>.<genexpr>  s:      ddd\T\III&IIddddddr7   r   )r   r  r  r4   r  rY   s     `r5   r  zQueryBuilder._columns_sql  sJ     $$HHddddVZVcddddd % 
 
 	
r7   c                x    d                     d                    fd| j        D                                 S )Nz VALUES ({values})z),(c              3  Z   K   | ]%}d                      fd|D                       V  &dS )r  c              3  8   K   | ]} |j         dd d dV  dS r  r   r  s     r5   r]  z5QueryBuilder._values_sql.<locals>.<genexpr>.<genexpr>  s=      ``TXOOOOO``````r7   N)r  )rx  rowrY   s     r5   r]  z+QueryBuilder._values_sql.<locals>.<genexpr>  sV        eh````\_`````     r7   )rp  )r   r  r  r]   s    `r5   r  zQueryBuilder._values_sql  sZ    #**::    lplx     + 
 
 	
r7   c                R    d                      | j        j        dddi|          S )Nz INTO {table}ra  Fr<   rQ   r  r]   s     r5   r  zQueryBuilder._into_sql  s=    %%,$$,HHHHH & 
 
 	
r7   c                x    d                     d                    fd| j        D                                 S )Nz FROM {selectable}r  c              3  8   K   | ]} |j         dd d dV  dS Tr  NrQ   r   r  s     r5   r]  z)QueryBuilder._from_sql.<locals>.<genexpr>  s>      rr]c X X XQW X Xrrrrrrr7   r  )r   r  r:  r  s     `r5   r  zQueryBuilder._from_sql  sH    #**xxrrrrgkgqrrrrr + 
 
 	
r7   c                x    d                     d                    fd| j        D                                 S )Nz USING {selectable}r  c              3  8   K   | ]} |j         dd d dV  dS r  r   r  s     r5   r]  z*QueryBuilder._using_sql.<locals>.<genexpr>  s>      ss]c X X XQW X Xssssssr7   r  )r   r  r  r  s     `r5   r  zQueryBuilder._using_sql  sH    $++xxssssgkgrsssss , 
 
 	
r7   c                x    d                     d                    fd| j        D                                 S )Nz FORCE INDEX ({indexes})r  c              3  2   K   | ]} |j         di V  d S r[   r   rx  r  rY   s     r5   r]  z0QueryBuilder._force_index_sql.<locals>.<genexpr>  s5      VV]U]44V44VVVVVVr7   indexes)r   r  r  r]   s    `r5   r  zQueryBuilder._force_index_sql  sG    )00HHVVVV$BUVVVVV 1 
 
 	
r7   c                x    d                     d                    fd| j        D                                 S )Nz USE INDEX ({indexes})r  c              3  2   K   | ]} |j         di V  d S r[   r   r  s     r5   r]  z.QueryBuilder._use_index_sql.<locals>.<genexpr>  s5      TT]U]44V44TTTTTTr7   r  )r   r  r  r]   s    `r5   r  zQueryBuilder._use_index_sql  sG    '..HHTTTT$BSTTTTT / 
 
 	
r7   c                T    d                      | j        j        d|dd|          S )Nz PREWHERE {prewhere}Tr   rb  )r  rQ   )r   r  r\   r4   r   rY   s      r5   r  zQueryBuilder._prewhere_sql  s?    %,,,T_,\
T\\U[\\ - 
 
 	
r7   c                T    d                      | j        j        d|dd|          S )Nz WHERE {where}Tr  )r  rQ   )r   r  r\   r  s      r5   r  zQueryBuilder._where_sql  s8    &&-AT\-A-qZbf-q-qjp-q-q&rrrr7   r|  groupby_aliasc           	     j   g }d | j         D             }| j        D ]b}|r;|j        r4|j        |v r+|                    t	          |j        |p|                     ?|                     |j        d||d|           cd                    d                    |                    }| j        r|dz   S |S )a  
        Produces the GROUP BY part of the query.  This is a list of fields. The clauses are stored in the query under
        self._groupbys as a list fields.

        If an groupby field is used in the select clause,
        determined by a matching alias, and the groupby_alias is set True
        then the GROUP BY clause will use the alias,
        otherwise the entire field will be rendered as SQL.
        c                    h | ]	}|j         
S rQ   r2   rw  s     r5   ry  z*QueryBuilder._group_sql.<locals>.<setcomp>      ;;;AG;;;r7   r   r|  z GROUP BY {groupby}r  )r  z WITH TOTALSrQ   )	rl  r  r,   r   r"   r\   r   r  r  )	r4   r   r|  r  rY   r  r  r@   sqls	            r5   r  zQueryBuilder._group_sql  s      ;;T];;;^ 	r 	rE r r@P1P1P}U[:J:XjYYZZZZ}u}p
Ueppioppqqqq#**388G3D3D*EE 	(''
r7   orderby_aliasc                l   g }d | j         D             }| j        D ]q\  }}|r'|j        r |j        |v rt          |j        |p|          n |j        d	||d|}	|                    |d                    |	|j                  n|	           rd                    d                    |                    S )
a  
        Produces the ORDER BY part of the query.  This is a list of fields and possibly their directionality, ASC or
        DESC. The clauses are stored in the query under self._orderbys as a list of tuples containing the field and
        directionality (which can be None).

        If an order by field is used in the select clause,
        determined by a matching, and the orderby_alias
        is set True then the ORDER BY clause will use
        the alias, otherwise the field will be rendered as SQL.
        c                    h | ]	}|j         
S rQ   r2   rw  s     r5   ry  z,QueryBuilder._orderby_sql.<locals>.<setcomp>  r  r7   r  Nrz  r{  r~  r  r  rQ   )	rl  r2  r,   r"   r\   r   r   rm  r  )
r4   r   r|  r  rY   r  r  r@   r  r|  s
             r5   rn  zQueryBuilder._orderby_sql  s    " ;;T];;;%)^ 		 		!E> !g%*[g5:[DT5T5T ek+;+IzJJJ"U]fjK[ff_eff  NNTbTn!((d>;O(PPPtx    %++CHHW4E4E+FFFr7   c                    dS )Nz WITH ROLLUPrQ   rB   s    r5   r  zQueryBuilder._rollup_sql  s    ~r7   c                R    d                      | j        j        dd|i|          S )Nz HAVING {having}r   )r  rQ   )r   r  r\   r  s      r5   r  zQueryBuilder._having_sql  s6    !((0E0E0f0fQ[0f_e0f0f(gggr7   c                R    d                      | j        j        dd|i|          S )Nz QUALIFY {qualify}r   )r  rQ   )r   r  r\   r  s      r5   r  zQueryBuilder._qualify_sql  s6    #**3I4>3I3j3jU_3jci3j3j*kkkr7   c                    d| j          S )Nz OFFSET rE  rB   s    r5   rp  zQueryBuilder._offset_sql  s    ($,(((r7   c                    d| j          S )Nz LIMIT r@  rB   s    r5   ro  zQueryBuilder._limit_sql  s    &&&&r7   c                x    d                     d                    fd| j        D                                 S )Nz
 SET {set}r  c              3     K   | ]C\  }}d                       |j        di t          d           |j        di           V  DdS )z{field}={value}F)r  )r@   rm  NrQ   )r   r\   ry  )rx  r@   rm  rY   s      r5   r]  z(QueryBuilder._set_sql.<locals>.<genexpr>#  s         !E5 "(('%-MM$ve*L*L*LMMUbUZUbUlUlekUlUl )       r7   )r  )r   r  r  r]   s    `r5   r  zQueryBuilder._set_sql!  s[    ""     %)M	     # 
 
 	
r7   c                     || g|R i |S )a  Call a function on the current object and return the result.

        Example usage:

        .. code-block:: python

            from pypika import Query, functions as fn
            from pypika.queries import QueryBuilder

            def rows_by_group(query: QueryBuilder, *groups) -> QueryBuilder:
                return (
                    query
                    .select(*groups, fn.Count("*").as_("n_rows"))
                    .groupby(*groups)
                )

            base_query = Query.from_("table")

            col1_agg = base_query.pipe(rows_by_group, "col1")
            col2_agg = base_query.pipe(rows_by_group, "col2")
            col1_col2_agg = base_query.pipe(rows_by_group, "col1", "col2")

        Makes chaining functions together easier, especially when the functions are
        defined elsewhere. For example, you could define a function that filters
        rows by a date range and then group by a set of columns:


        .. code-block:: python

            from datetime import datetime, timedelta

            from pypika import Field

            def days_since(query: QueryBuilder, n_days: int) -> QueryBuilder:
                return (
                    query
                    .where("date" > fn.Date(datetime.now().date() - timedelta(days=n_days)))
                )

            (
                base_query
                .pipe(days_since, n_days=7)
                .pipe(rows_by_group, "col1", "col2")
            )
        rQ   )r4   funcr	  rY   s       r5   pipezQueryBuilder.pipe+  s%    \ tD*4***6***r7   )
rd  r  rk  r_   r.  r/  r  r_   r  r_   r   )r  r  r.   r/   r  r  r  r  r.   r/   )r  r+   r:   r-   r.   r/   )r=   r   r.   r/   )r   r   r.   r/   r.   r/   )r|  r  r   r  r.   r/   )r   r   r.   r/   r   r  r.   r/   )r   r  r.   r/   )r   r  rY   r   r.   r/   )r6  r   rY   r   r.   r/   )rx   r  r  r   r.   r  )rx   r  r.   r  r  r  r  )r@   r<  rm  r   r.   r/   )rA  rA  r.   r/   )rx   r   r.   rE  r1   )rG  rH  r   r   r.   rI  )r|  r-   r.   r/   )r|  r   r.   r/   )rS  r   r.   r/   )r.   rU  )r  rX  r.   r/   )r=   ry   r.   r_   )r|  r   r.   r_   )rb  r(   r.   r/   rL   )r^   r(   r.   r_   ri   rY   ry  r.   r/   r  r  )rs  r-   r.   r-   rh   )F)r  r_   rY   r   r.   r-   r   )NNT)
r   r   r|  r   r  r_   rY   r   r.   r-   )
r   r   r|  r   r  r_   rY   r   r.   r-   )lrM   rN   rO   r   rj  r}  r~  r  r   	QUERY_CLSr   r6   r  r    r   r  r  r   r   r  r   r   r   r  r  r  r  r  r  r  r  r  r  r  r  r  r=  r   r  r  r  r  r   r$  r'  r*  r-  r0  r2  r>  rC  rI  rL  rO  rQ  rS  r  rV  rZ  r^  rA  rI   r   rL  r  r  r  rW  rb  rf  r  r  r  r   r   rc   rv   rg   r  r\   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rn  r  r  r  rp  ro  r  r  rj   rk   s   @r5   r(   r(     s	        
 J!I $(+/*6 9# 9# 9# 9# 9# 9# 9#v   $ 7 7 7 W74 #4 #4 #4 W#4J    W Q Q Q WQ 	\ 	\ 	\ W	\ ! ! ! W! Q Q Q WQ 
' 
' 
' W
'    W    W 5 5 5 W5 3 3 3 W3    W       W     W ( ( ( W( 
% 
% 
% W
% & & & W& ' ' ' W' ( ( ( W( ! ! ! W! 2 2 2 W22 @ @ @ W@ V^VdB B B B WB&/ / / /. . . .4 4 4 4/ / / /5 5 5 5/ / / /4 4 4 4/ / / /. . . .    W    W ] ] ] W] a a a Wa a a a Wa a a a Wa ] ] ] W] - - - W-! ! ! !% % % %! ! ! ! ! ! ! W!           
 \ \ \ \ \\	= 	= 	= 	=# # # #"' ' ' '   
! 
! 
! 
!? ? ? ?   *" " " "w w w w"2 2 2 2      & & & &M M M M3 3 3 3{ { { { {z   
 
 
 
   
   

 
 
 

 
 
 

 
 
 

    \S S S S
 
 
 
 

 
 
 

 
 
 


 
 
 
 


 
 
 
 


 
 
 


 
 
 


 
 
 
 

s s s s s
 "&'+"	    B "&'+"	G G G G G@   h h h h hl l l l l) ) ) )' ' ' '
 
 
 
.+ .+ .+ .+ .+ .+ .+r7   c                  8    e Zd ZddZdddZddZddZddZdS )r  rT   r'   rx   r  r  r   r  r-   r.   r/   c                >    || _         || _        || _        || _        d S r1   )rT   rx   r  r  )r4   rT   rx   r  r  s        r5   r6   zJoiner.__init__]  s"    
	$r7   Nr   Criterion | Nonecollater   c                    |(t          d                    | j                            | j                            t          | j        | j        ||                     | j        S )NzIParameter 'criterion' is required for a {type} JOIN but was not supplied.r   )r   r   r  rT   rb  JoinOnrx   r  )r4   r   r  s      r5   onz	Joiner.onc  sb    44:FF4P4P  
 	
6$)TXy'JJKKKzr7   r6  r   c                \   |s(t          d                    | j                            d }|D ]D}t          || j        j        d                   t          || j                  k    }||n||z  }E| j                            t          | j        | j	        |                     | j        S )NzFParameter 'fields' is required for a {type} JOIN but was not supplied.r  r   r<   )
r   r   r  r   rT   r:  rx   rb  r  r  )r4   r6  r   r@   constituents        r5   on_fieldzJoiner.on_fieldm  s     	[bbhlhwbxx   	 	V 	VETZ-=a-@AAAU5X\XaEbEbEbbK'0'8i+>UII
6$)TXyAABBBzr7   c                    |st          d          | j                            t          | j        | j        d |D                                  | j        S )NzUParameter 'fields' is required when joining with a using clause but was not supplied.c                ,    g | ]}t          |          S rQ   r>   )rx  r@   s     r5   r  z Joiner.using.<locals>.<listcomp>  s    :\:\:\E5<<:\:\:\r7   )r   rT   rb  	JoinUsingrx   r  )r4   r6  s     r5   usingzJoiner.using{  sX     	y wxxx
9TY:\:\U[:\:\:\]]^^^zr7   c                ~    | j                             t          | j        t          j                             | j         S )zReturn cross join)rT   rb  rX  rx   r   r/  rB   s    r5   r/  zJoiner.cross  s.    
4	8>::;;;zr7   )
rT   r'   rx   r  r  r   r  r-   r.   r/   r1   )r   r  r  r   r.   r'   )r6  r   r.   r'   )r.   r'   )rM   rN   rO   r6   r  r  r  r/  rQ   r7   r5   r  r  \  s}        % % % %               r7   r  c                  >    e Zd ZddZddZddZedd            ZdS )rX  rx   r   r  r   r.   r/   c                "    || _         || _        d S r1   )rx   r  r  s      r5   r6   zJoin.__init__  s    	r7   rY   r   r-   c                    d                      | j        j        dddd|          }| j        j        r!d                     || j        j                  S |S )NzJOIN {table}Tr  r<   z{type} {join})r  r   rQ   )r   rx   r\   r  rm  )r4   rY   r  s      r5   r\   zJoin.get_sql  sl    ###$)#MTdMMfMM $ 
 
 8> 	I"))s)HHH
r7   r:  Sequence[Table]r  c                    d S r1   rQ   r4   r:  r  s      r5   r_  zJoin.validate      r7   r  r  r  c                F    | j                             ||          | _         dS X  
        Replaces all occurrences of the specified table with the new table. Useful when reusing
        fields across queries.

        :param current_table:
            The table to be replaced.
        :param new_table:
            The table to replace with.
        :return:
            A copy of the join with the tables replaced.
        N)rx   r  r  s      r5   r  zJoin.replace_table  s!     I++M9EE			r7   N)rx   r   r  r   r.   r/   rh   r:  r  r  r  r.   r/   r  )rM   rN   rO   r6   r\   r_  r    r  rQ   r7   r5   rX  rX    sv                  F F F WF F Fr7   rX  c                  N     e Zd Zdd fdZd fdZddZedd            Z xZS )r  Nrx   r   r  r   criteriar(   r  r   r.   r/   c                h    t                                          ||           || _        || _        d S r1   )rW   r6   r   r  )r4   rx   r  r  r  rX   s        r5   r6   zJoinOn.__init__  s/    s###!r7   rY   r   r-   c                     t                      j        di |}d                    | | j        j        dddi|| j        r
d| j         nd          S )Nz{join} ON {criterion}{collate}rb  Tz	 COLLATE r   )r  r   r  rQ   )rW   r\   r   r   r  r4   rY   join_sqlrX   s      r5   r\   zJoinOn.get_sql  su    "577?,,V,,/66,dn,EEdEfEE26,F....B 7 
 
 	
r7   r:  r  r  c           
     P   t          d | j                                        D                       }t          |          d |D             z  | j        hz  }||z
  }|rIt	          d                    d                    t          t          |                                        d S )Nc                    g | ]	}|j         
S rQ   r<   )rx  fs     r5   r  z#JoinOn.validate.<locals>.<listcomp>  s    JJJAJJJr7   c                    h | ]	}|j         
S rQ   re  ri  s     r5   ry  z"JoinOn.validate.<locals>.<setcomp>  s    (F(F(Ft(F(F(Fr7   zInvalid join criterion. One field is required from the joined item and another from the selected table or an existing join.  Found [{tables}], )r   )	r  r   rW  rx   r   r   r  mapr-   )r4   r:  r  criterion_tablesavailable_tablesmissing_tabless         r5   r_  zJoinOn.validate  s    JJ1G1G1I1IJJJKKu::(F(Fv(F(F(FF$)T),<< 	YY_Y_99Sn%=%=>> Z` Z Z  	 	r7   r  r  r  c                x    | j         |k    r|n| j         | _         | j                            ||          | _        dS r  )rx   r   r  r  s      r5   r  zJoinOn.replace_table  s:     "&m!;!;II	55mYOOr7   r1   )
rx   r   r  r   r  r(   r  r   r.   r/   rh   r  r  	rM   rN   rO   r6   r\   r_  r    r  rj   rk   s   @r5   r  r    s              

 
 
 
 
 

 
 
 
 P P P WP P P P Pr7   r  c                  L     e Zd Zd fd	Zd fdZddZedd            Z xZS )r  rx   r   r  r   r6  rH  r.   r/   c                Z    t                                          ||           || _        d S r1   )rW   r6   r6  )r4   rx   r  r6  rX   s       r5   r6   zJoinUsing.__init__  s(    s###r7   rY   r   r-   c                     t                      j        di }d                    |d                    fd| j        D                                 S )Nz{join} USING ({fields})r  c              3  2   K   | ]} |j         di V  d S r[   r   )rx  r@   rY   s     r5   r]  z$JoinUsing.get_sql.<locals>.<genexpr>  s5      MMMEM33F33MMMMMMr7   )r  r6  rQ   )rW   r\   r   r  r6  r  s    ` r5   r\   zJoinUsing.get_sql  se    "577?,,V,,(//88MMMMMMMMM 0 
 
 	
r7   r:  r  r  c                    d S r1   rQ   r  s      r5   r_  zJoinUsing.validate  r  r7   r  r  r  c                n    | j         k    rn| j         | _         fd| j        D             | _        dS )r   c                <    g | ]}|                               S rQ   r  )rx  r@   r  r  s     r5   r  z+JoinUsing.replace_table.<locals>.<listcomp>  s)    ^^^u**=)DD^^^r7   N)rx   r6  r  s    ``r5   r  zJoinUsing.replace_table  sE     "&m!;!;II	^^^^^RVR]^^^r7   )rx   r   r  r   r6  rH  r.   r/   rh   r  r  r  rk   s   @r5   r  r    s             
 
 
 
 
 
    _ _ _ W_ _ _ _ _r7   r  c                     e Zd ZdZdZdZdZeZd9d:d	Z	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            Zed@d            Ze	 	 dAdBd#            ZedCd&            Zed=d'            ZdDd*ZdDd+ZdEd,ZdFd.ZdFd/ZdFd0ZdEd1ZdEd2ZdEd3ZdDd4Z dGd6Z!dEd7Z"dEd8Z#dS )Hr   z5
    Query builder used to build CREATE queries.
    r   r  Nrd  r  r.   r/   c                    d | _         d| _        d| _        d | _        g | _        g | _        d| _        d | _        g | _        d| _	        || _
        d | _        d | _        d | _        d | _        d | _        d S r  )_create_table
_temporary	_unlogged
_as_selectr  _period_fors_with_system_versioning_primary_key_uniques_if_not_existsrd  _foreign_key_foreign_key_reference_table_foreign_key_reference_foreign_key_on_update_foreign_key_on_deleter4   rd  s     r5   r6   zCreateQueryBuilder.__init__  s    !',$ # ,0)&*#7;#7;###r7   rY   ry  c                    |                     d| j                   |                     d| j                   |                     d| j                   d S Nr   r{  rd  ri  rj  r}  rd  r]   s     r5   r  z'CreateQueryBuilder._set_kwargs_defaults  R    ,8880$2KLLL)T\22222r7   r=   r  c                    | j         rt          d          t          |t                    r|nt          |          | _         dS )z
        Creates the table.

        :param table:
            An instance of a Table object or a string table name.

        :raises AttributeError:
            If the table is already created.

        :return:
            CreateQueryBuilder.
        z1'Query' object already has attribute create_tableN)r  r   ra   ry   r  s     r5   r  zCreateQueryBuilder.create_table  sF      	V !TUUU&0&>&>PUUE%LLr7   c                    d| _         dS )z^
        Makes the table temporary.

        :return:
            CreateQueryBuilder.
        TN)r  rB   s    r5   	temporaryzCreateQueryBuilder.temporary)  s     r7   c                    d| _         dS )z]
        Makes the table unlogged.

        :return:
            CreateQueryBuilder.
        TN)r  rB   s    r5   unloggedzCreateQueryBuilder.unlogged3  s     r7   c                    d| _         dS )z[
        Adds system versioning.

        :return:
            CreateQueryBuilder.
        TNr!  rB   s    r5   with_system_versioningz)CreateQueryBuilder.with_system_versioning=  s     (,$$$r7   r   str | tuple[str, str] | Columnc                   | j         rt          d          |D ]s}t          |t                    rt	          |          }n2t          |t
                    rt	          |d         |d                   }| j                            |           tdS )a  
        Adds the columns.

        :param columns:
            Type:  Union[str, TypedTuple[str, str], Column]

            A list of columns.

        :raises AttributeError:
            If the table is an as_select table.

        :return:
            CreateQueryBuilder.
        z.'Query' object already has attribute as_selectr   r   r   N)r  r   ra   r-   r   r   r  r   r4   r   r   s      r5   r   zCreateQueryBuilder.columnsG  s      ? 	S !QRRR 	) 	)F&#&& NFE** NF1I6!9MMMM  ((((	) 	)r7   r   r   r   c                X    | j                             t          |||                     dS )a&  
        Adds a PERIOD FOR clause.

        :param name:
            The period name.

        :param start_column:
            The column that starts the period.

        :param end_column:
            The column that ends the period.

        :return:
            CreateQueryBuilder.
        N)r   r   r   r   s       r5   
period_forzCreateQueryBuilder.period_fora  s-    " 	  4z!J!JKKKKKr7   c                `    | j                             |                     |                     dS )z
        Adds a UNIQUE constraint.

        :param columns:
            Type:  Union[str, Column]

            A list of columns.

        :return:
            CreateQueryBuilder.
        N)r#  r   _prepare_columns_inputr4   r   s     r5   uniquezCreateQueryBuilder.uniquet  s.     	T88AABBBBBr7   c                f    | j         rt          d          |                     |          | _         dS )a  
        Adds a primary key constraint.

        :param columns:
            Type:  Union[str, Column]

            A list of columns.

        :raises AttributeError:
            If the primary key is already defined.

        :return:
            CreateQueryBuilder.
        z0'Query' object already has attribute primary_keyN)r"  r   r=  r>  s     r5   primary_keyzCreateQueryBuilder.primary_key  s;       	U !STTT 77@@r7   list[str | Column]reference_tabler   reference_columns	on_deleter   	on_updatec                    | j         rt          d          |                     |          | _         || _        |                     |          | _        || _        || _        dS )a  
        Adds a foreign key constraint.

        :param columns:
            Type:  List[Union[str, Column]]

            A list of foreign key columns.

        :param reference_table:
            Type: Union[str, Table]

            The parent table name.

        :param reference_columns:
            Type: List[Union[str, Column]]

            Parent key columns.

        :param on_delete:
            Type: ReferenceOption

            Delete action.

        :param on_update:
            Type: ReferenceOption

            Update option.

        :raises AttributeError:
            If the foreign key is already defined.

        :return:
            CreateQueryBuilder.
        z0'Query' object already has attribute foreign_keyN)r%  r   r=  r&  r'  r)  r(  )r4   r   rC  rD  rE  rF  s         r5   foreign_keyzCreateQueryBuilder.foreign_key  sk    V  	U !STTT 77@@,;)&*&A&ABS&T&T#&/#&/###r7   query_builderr(   c                    | j         rt          d          t          |t                    st	          d          || _        dS )z
        Creates the table from a select statement.

        :param query_builder:
            The query.

        :raises AttributeError:
            If columns have been defined for the table.

        :return:
            CreateQueryBuilder.
        z,'Query' object already has attribute columnsz.Expected 'item' to be instance of QueryBuilderN)r  r   ra   r(   r   r  )r4   rI  s     r5   	as_selectzCreateQueryBuilder.as_select  sK     = 	Q !OPPP-66 	NLMMM'r7   c                    d| _         d S r  r$  rB   s    r5   if_not_existsz CreateQueryBuilder.if_not_exists      "r7   r   r-   c                    |                      |           | j        sdS | j        s	| j        sdS  | j        di |}| j        r| | j        di |z   S  | j        di |} | j        di |}| d| d| S )zr
        Gets the sql statement string.

        :return: The create table statement.
        :rtype: str
        r   z ()rQ   )r  r  r  r  _create_table_sql_as_select_sql	_body_sql_table_options_sql)r4   rY   r  bodytable_optionss        r5   r\   zCreateQueryBuilder.get_sql  s     	!!&)))! 	2} 	T_ 	2-t-7777? 	@"5$"5"?"?"?"???t~''''//99&9988$88888r7   c           	         d}| j         rd}n	| j        rd}d}| j        rd}d                    || | j        j        di |          S )Nr   z
TEMPORARY z	UNLOGGED zIF NOT EXISTS z/CREATE {table_type}TABLE {if_not_exists}{table})
table_typerN  r=   rQ   )r  r  r$  r   r  r\   )r4   rY   rY  rN  s       r5   rR  z$CreateQueryBuilder._create_table_sql  sy    
? 	%%JJ^ 	%$J 	-,M@GG!',$$,66v66 H 
 
 	
r7   c                "    d}| j         r|dz  }|S )Nr   z WITH SYSTEM VERSIONINGr5  )r4   rY   rW  s      r5   rU  z%CreateQueryBuilder._table_options_sql  s#    ' 	766Mr7   rI  c                *    fd| j         D             S )Nc                *    g | ]} |j         d i S rQ   r   rx  r   rY   s     r5   r  z6CreateQueryBuilder._column_clauses.<locals>.<listcomp>  s+    EEEV((((EEEr7   )r  r]   s    `r5   _column_clausesz"CreateQueryBuilder._column_clauses  s    EEEEt}EEEEr7   c                *    fd| j         D             S )Nc                *    g | ]} |j         d i S r]  r   )rx  r;  rY   s     r5   r  z:CreateQueryBuilder._period_for_clauses.<locals>.<listcomp>  s-    QQQ"
",,V,,QQQr7   )r   r]   s    `r5   _period_for_clausesz&CreateQueryBuilder._period_for_clauses  s     QQQQt?PQQQQr7   c                *    fd| j         D             S )Nc                z    g | ]7}d                      d                    fd|D                                 8S )zUNIQUE ({unique})r  c              3  2   K   | ]} |j         di V  d S r[   r   r^  s     r5   r]  zDCreateQueryBuilder._unique_key_clauses.<locals>.<listcomp>.<genexpr>  s8      6j6jY_7Jv7J7T7TV7T7T6j6j6j6j6j6jr7   )r?  )r   r  )rx  r?  rY   s     r5   r  z:CreateQueryBuilder._unique_key_clauses.<locals>.<listcomp>  s\     
 
 
  &&chh6j6j6j6jci6j6j6j.j.j&kk
 
 
r7   )r#  r]   s    `r5   _unique_key_clausesz&CreateQueryBuilder._unique_key_clauses  s0    
 
 
 
-
 
 
 	
r7   c                x    d                     d                    fd| j        D                                 S )NzPRIMARY KEY ({columns})r  c              3  2   K   | ]} |j         di V  d S r[   rf  r^  s     r5   r]  z9CreateQueryBuilder._primary_key_clause.<locals>.<genexpr>$  7      [[v0V0::6::[[[[[[r7   r  )r   r  r"  r]   s    `r5   _primary_key_clausez&CreateQueryBuilder._primary_key_clause"  sG    (//HH[[[[IZ[[[[[ 0 
 
 	
r7   c                L   d                     d                    fd| j        D                        | j        j        di d                    fd| j        D                                 }| j        r|d| j        j        z   z  }| j        r|d| j        j        z   z  }|S )	NzEFOREIGN KEY ({columns}) REFERENCES {table_name} ({reference_columns})r  c              3  2   K   | ]} |j         di V  d S r[   rf  r^  s     r5   r]  z9CreateQueryBuilder._foreign_key_clause.<locals>.<genexpr>)  rj  r7   c              3  2   K   | ]} |j         di V  d S r[   rf  r^  s     r5   r]  z9CreateQueryBuilder._foreign_key_clause.<locals>.<genexpr>+  s7      &o&o':v':'D'DV'D'D&o&o&o&o&o&or7   )r   r"  rD  z ON DELETE z ON UPDATE rQ   )	r   r  r%  r&  r\   r'  r)  rm  r(  )r4   rY   r[  s    ` r5   _foreign_key_clausez&CreateQueryBuilder._foreign_key_clause'  s    X__HH[[[[IZ[[[[[@t8@JJ6JJ!hh&o&o&o&oSWSn&o&o&ooo ` 
 

 & 	Hmd&A&GGGF& 	Hmd&A&GGGFr7   c                "    | j         di |}| | j        di |z  }| | j        di |z  }| j        r |                     | j        di |           | j        r |                     | j        di |           d                    |          S )Nr  rQ   )	r_  rb  rg  r"  r   rk  r%  ro  r  )r4   rY   r  s      r5   rT  zCreateQueryBuilder._body_sql4  s    &$&0000+4+55f555+4+55f555 	?NN343==f==>>> 	?NN343==f==>>>xx   r7   c                N    d                      | j        j        di |          S )Nz AS ({query})r  rQ   )r   r  r\   r]   s     r5   rS  z!CreateQueryBuilder._as_select_sql@  s7    %%)$/)33F33 & 
 
 	
r7   r   c                    d |D             S )Nc                Z    g | ](}t          |t                    r|nt          |          )S rQ   )ra   r   )rx  r   s     r5   r  z=CreateQueryBuilder._prepare_columns_input.<locals>.<listcomp>F  s1    aaav:ff55I6&>>aaar7   rQ   r>  s     r5   r=  z)CreateQueryBuilder._prepare_columns_inputE  s    aaY`aaaar7   c                *    |                                  S r1   r   rB   s    r5   r   zCreateQueryBuilder.__str__H  r`  r7   c                *    |                                  S r1   rs  rB   s    r5   r   zCreateQueryBuilder.__repr__K  r`  r7   r1   rd  r  r.   r/   r  r=   r  r.   r/   r  r   r7  r.   r/   )r   r   r   r   r.   r/   )r   r   r.   r/   )NN)r   rB  rC  r   rD  rB  rE  r   rF  r   r.   r/   )rI  r(   r.   r/   rh   rL   )r.   rI  )r   rB  r.   r   )$rM   rN   rO   r   rj  r}  r~  r   r  r6   r  r    r  r1  r3  r6  r   r;  r?  rA  rH  rK  rN  r\   rR  rU  r_  rb  rg  rk  ro  rT  rS  r=  r   r   rQ   r7   r5   r   r     s         JI< < < < <$3 3 3 3
 Q Q Q WQ$    W    W , , , W, ) ) ) W)2 L L L WL$ C C C WC A A A WA&  &*%)00 00 00 00 W00d ( ( ( W(* # # # W#9 9 9 92
 
 
 
"   F F F FR R R R
 
 
 

 
 
 

   
! 
! 
! 
!
 
 
 

b b b b        r7   r   c                      e Zd Z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
ddZddZddZdS )r  r.   r/   c                Z    d | _         g | _        d | _        d | _        d| _        d| _        d S r  )_indexr  _tabler  
_is_uniquer$  rB   s    r5   r6   zCreateIndexBuilder.__init__P  s3    #r7   r  r  c                    || _         d S r1   )r{  r4   r  s     r5   r  zCreateIndexBuilder.create_indexX  rB  r7   r   r7  c                    |D ]s}t          |t                    rt          |          }n2t          |t                    rt          |d         |d                   }| j                            |           td S )Nr   r   r   )ra   r-   r   r   r  r   r9  s      r5   r   zCreateIndexBuilder.columns\  s     	) 	)F&#&& NFE** NF1I6!9MMMM  ((((	) 	)r7   r=   r  c                    || _         d S r1   )r|  r  s     r5   r  zCreateIndexBuilder.one  rB  r7   r   r  c                F    | j         r| xj         |z  c_         dS || _         dS )z-
        Partial index where clause.
        N)r  r  s     r5   r  zCreateIndexBuilder.wherei  s-    
 < 	%LLI%LLLL$DLLLr7   c                    d| _         d S r  )r}  rB   s    r5   r?  zCreateIndexBuilder.uniques      r7   c                    d| _         d S r  rM  rB   s    r5   rN  z CreateIndexBuilder.if_not_existsw  rO  r7   r-   c                   | j         rt          | j                   dk    rt          d          | j        st          d          d                    d | j         D                       }| j        rdnd}| j        rdnd}d	| d
| d| j         d| j         d| d}| j        r|d| j         z  }|	                    dd          S )Nr   z#Cannot create index without columnsz!Cannot create index without tabler  c                    g | ]	}|j         
S rQ   r   )rx  cs     r5   r  z.CreateIndexBuilder.get_sql.<locals>.<listcomp>  s     ? ? ?A ? ? ?r7   UNIQUEr   zIF NOT EXISTSzCREATE z INDEX r  z ON (rQ  z WHERE z  )
r  r   r   r|  r  r}  r$  r{  r  r  )r4   columns_str
unique_strif_not_exists_strbase_sqls        r5   r\   zCreateIndexBuilder.get_sql{  s    } 	HDM 2 2a 7 7 !FGGG{ 	F !DEEEii ? ? ? ? ?@@!%8XXb
/3/BJOOqZqq0AqqDKqqUYU`qqcnqqq< 	10$,000Hc***r7   c                *    |                                  S r1   r   rB   s    r5   r   zCreateIndexBuilder.__str__  r`  r7   c                *    |                                  S r1   rs  rB   s    r5   r   zCreateIndexBuilder.__repr__  r`  r7   Nr  )r  r  r.   r/   rx  rw  r  rL   )rM   rN   rO   r6   r    r  r   r  r  r?  rN  r\   r   r   rQ   r7   r5   r  r  O  s$       $ $ $ $    W ) ) ) W)    W % % % W%    W # # # W#+ + + +        r7   r  c                      e Zd ZdZdZdZdZeZd#d$d	Z	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d,dZd-d Zd.d!Zd.d"ZdS )/r  z3
    Query builder used to build DROP queries.
    r   r  Nrd  r  r.   r/   c                >    d | _         d| _        d | _        || _        d S )Nr   )_drop_target_kind_drop_target
_if_existsrd  r*  s     r5   r6   zDropQueryBuilder.__init__  s$    !%46r7   rY   ry  c                    |                     d| j                   |                     d| j                   |                     d| j                   d S r,  r-  r]   s     r5   r  z%DropQueryBuilder._set_kwargs_defaults  r.  r7   r
  Database | strc                ~    t          |t                    r|nt          |          }|                     d|           d S )NDATABASE)ra   r   _set_target)r4   r
  targets      r5   r  zDropQueryBuilder.drop_database  s>    '(;;S(ASASV,,,,,r7   r=   r  c                ~    t          |t                    r|nt          |          }|                     d|           d S )NTABLE)ra   ry   r  )r4   r=   r  s      r5   r  zDropQueryBuilder.drop_table  s<    $UE22De&)))))r7   r  r-   c                2    |                      d|           d S )NUSERr  )r4   r  s     r5   r  zDropQueryBuilder.drop_user      &&&&&r7   r  c                2    |                      d|           d S )NVIEWr  )r4   r  s     r5   r  zDropQueryBuilder.drop_view  r  r7   r  c                2    |                      d|           d S )NINDEXr  r  s     r5   r  zDropQueryBuilder.drop_index  s    %(((((r7   c                    d| _         d S r  )r  rB   s    r5   	if_existszDropQueryBuilder.if_exists  r  r7   kindr  Database | Table | strc                N    | j         rt          d          || _        || _         d S )Nz4'DropQuery' object already has attribute drop_target)r  r   r  )r4   r  r  s      r5   r  zDropQueryBuilder._set_target  s3     	Y !WXXX!%"r7   r   c                   |                      |           | j        rdnd}d}t          | j        t          t
          f          r | j        j        di |}nt          | j        | j                  }d	                    | j
        ||          S )Nz
IF EXISTS r   zDROP {kind} {if_exists}{name})r  r  r:   rQ   )r  r  ra   r  r   ry   r\   r"   rj  r   r  )r4   rY   r  target_names       r5   r\   zDropQueryBuilder.get_sql  s    !!&)))$(O;LL	d'(E):;; 	L3$+3==f==KK'(94?KKK.55'9; 6 
 
 	
r7   c                *    |                                  S r1   r   rB   s    r5   r   zDropQueryBuilder.__str__  r`  r7   c                *    |                                  S r1   rs  rB   s    r5   r   zDropQueryBuilder.__repr__  r`  r7   r1   rv  r  )r
  r  r.   r/   rw  )r  r-   r.   r/   )r  r-   r.   r/   )r  r-   r.   r/   r  )r  r-   r  r  r.   r/   rh   rL   )rM   rN   rO   r   rj  r}  r~  r   r  r6   r  r    r  r  r  r  r  r  r  r\   r   r   rQ   r7   r5   r  r    ss         JI    3 3 3 3
 - - - W- * * * W* ' ' ' W' ' ' ' W' ) ) ) W)    W# # # #
 
 
 
        r7   r  )r   r   rY   r   r.   r   )r   r   r.   r   )C
__future__r   syscollections.abcr   r   	functoolsr   typingr   r   r	   r
   pypika.enumsr   r   r   r   pypika.termsr   r   r   r   r   r   r   r   r   r   r   r   r   pypika.utilsr   r   r   r   r    r!   r"   r#   version_infor&   typing_extensions
__author__	__email__r'   r+   rS   rm   r   ry   r   r   r   r   r#  r   r*  r(   r  rX  r  r  r   r  r  rQ   r7   r5   <module>r     sG   " " " " " " 



 $ $ $ $ $ $             7 7 7 7 7 7 7 7 7 7 7 7 J J J J J J J J J J J J                             	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	  +
7""******
	 WT(((       6$ $ $ $ $: $ $ $$       6) ) ) ) )v ) ) )}9 }9 }9 }9 }9J }9 }9 }9@   2#, #, #, #, #, #, #, #,L   "       & @- @- @- @- @- @- @- @-FW: W: W: W: W:J W: W: W:tW+ W+ W+ W+ W+:t W+ W+ W+t* * * * *WR[ * * *ZF F F F F F F FB(P (P (P (P (PT (P (P (PV_ _ _ _ _ _ _ _@W W W W W W W Wt
= = = = = = = =@H H H H H H H H H Hr7   