U
    fY                     @   s  d Z ddlZddlZddlZddlmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ dZG dd deZdd Zd7ddZd8ddZd9ddZd:ddZG dd deZG dd deZG dd deZG dd  d eZG d!d" d"eZG d#d$ d$eZ G d%d& d&eZ!G d'd( d(eZ"G d)d* d*e"Z#G d+d, d,e"Z$G d-d. d.eZ%G d/d0 d0eZ&G d1d2 d2eZ'G d3d4 d4eZ(G d5d6 d6eZ)dS );zImplementation of Statements.    N   )ProgrammingErrorNotSupportedError)
ExprParser)LockContention)DbDoc)
deprecated)Result)mysqlxpb_enumz&The given index name "{}" is not validc                   @   s   e Zd ZdZdd ZdS )ExprzExpression wrapper.c                 C   s
   || _ d S N)expr)selfr    r   4/tmp/pip-unpacked-wheel-mzf9r1ws/mysqlx/statement.py__init__0   s    zExpr.__init__N)__name__
__module____qualname____doc__r   r   r   r   r   r   .   s   r   c                  G   s*   t | dkr&t| d ttfr&| d S | S )zParse flexible parameters.r   r   )len
isinstancelisttuple)valuesr   r   r   flexible_params4   s    r    c                 C   sP   d|kr8| d dkr | d dkp6| d dko6| d dkS | d dkoN| d dkS )zCheck if the given identifier is quoted.

    Args:
        identifier (string): Identifier to check.
        sql_mode (Optional[string]): SQL mode.

    Returns:
        `True` if the identifier has backtick quotes, and False otherwise.
    ANSI_QUOTESr   `"r   
identifiersql_moder   r   r   is_quoted_identifier;   s
    
r$   c                 C   s<   t | dkrdS d|kr*d| ddS d| ddS )	a@  Quote the given identifier with backticks, converting backticks (`) in
    the identifier name with the correct escape sequence (``).

    Args:
        identifier (string): Identifier to quote.
        sql_mode (Optional[string]): SQL mode.

    Returns:
        A string with the identifier quoted with backticks.
    r   z``r   z"{0}"r    z""z`{0}`r   )r   formatreplacer!   r   r   r   quote_identifierK   s
    r'   c                    s   d  fdd| D S )a  Quote the given multi-part identifier with backticks.

    Args:
        identifiers (iterable): List of identifiers to quote.
        sql_mode (Optional[string]): SQL mode.

    Returns:
        A string with the multi-part identifier quoted with backticks.
    .c                    s   g | ]}t | qS r   )r'   ).0r"   r#   r   r   
<listcomp>g   s   z.quote_multipart_identifier.<locals>.<listcomp>)join)Zidentifiersr#   r   r*   r   quote_multipart_identifier]   s    
r-   c                 C   s^   d|krdnd}||kr"d |nd}||d}t|dkrB| n|d ||d |fS )	zParse table name.

    Args:
        default_schema (str): The default schema.
        table_name (str): The table name.
        sql_mode(Optional[str]): The SQL mode.

    Returns:
        str: The parsed table name.
    r   r    r   z.{0}r(   r   r   r   )r%   splitr   strip)Zdefault_schemaZ
table_namer#   quote	delimitertempr   r   r   parse_table_namek   s    r3   c                   @   s   e Zd ZdZd"ddZedd Zedd Zed	d
 Zej	dd
 Zedd Z
edd Zej	dd Zedd Zej	dd Zedd Zedd Zej	dd Zdd Zdd Zdd Zdd  Zd!S )#	Statementa	  Provides base functionality for statement objects.

    Args:
        target (object): The target database object, it can be
                         :class:`mysqlx.Collection` or :class:`mysqlx.Table`.
        doc_based (bool): `True` if it is document based.
    Tc                 C   s@   || _ || _|r| nd | _d | _d| _d| _d| _d| _d S )Nr   TF)	_target
_doc_basedget_connection_connection_stmt_id_exec_counter_changed	_prepared_deallocate_prepare_executer   target	doc_basedr   r   r   r      s    zStatement.__init__c                 C   s   | j S )z#object: The database object target.)r5   r   r   r   r   r?      s    zStatement.targetc                 C   s   | j jS )z*:class:`mysqlx.Schema`: The Schema object.)r5   schemarA   r   r   r   rB      s    zStatement.schemac                 C   s   | j S )zXReturns this statement ID.

        Returns:
            int: The statement ID.
        r9   rA   r   r   r   stmt_id   s    zStatement.stmt_idc                 C   s
   || _ d S r   rC   r   valuer   r   r   rD      s    c                 C   s   | j S )z5int: The number of times this statement was executed.r:   rA   r   r   r   exec_counter   s    zStatement.exec_counterc                 C   s   | j S )z+bool: `True` if this statement has changes.r;   rA   r   r   r   changed   s    zStatement.changedc                 C   s
   || _ d S r   rI   rE   r   r   r   rJ      s    c                 C   s   | j S )z1bool: `True` if this statement has been prepared.r<   rA   r   r   r   prepared   s    zStatement.preparedc                 C   s
   || _ d S r   rK   rE   r   r   r   rL      s    c                 C   s
   | j dkS )zDbool: `True` if this statement was executed more than once.
        r   rG   rA   r   r   r   repeated   s    zStatement.repeatedc                 C   s   | j S )zBbool: `True` to deallocate + prepare + execute statement.
        r=   rA   r   r   r   deallocate_prepare_execute   s    z$Statement.deallocate_prepare_executec                 C   s
   || _ d S r   rN   rE   r   r   r   rO      s    c                 C   s   | j S )zkCheck if it is document based.

        Returns:
            bool: `True` if it is document based.
        )r6   rA   r   r   r   is_doc_based   s    zStatement.is_doc_basedc                 C   s   |  j d7  _ dS )z@Increments the number of times this statement has been executed.r   NrG   rA   r   r   r   increment_exec_counter   s    z Statement.increment_exec_counterc                 C   s
   d| _ dS )z<Resets the number of times this statement has been executed.r   NrG   rA   r   r   r   reset_exec_counter   s    zStatement.reset_exec_counterc                 C   s   t dS zqExecute the statement.

        Raises:
           NotImplementedError: This method must be implemented.
        NNotImplementedErrorrA   r   r   r   execute   s    zStatement.executeN)T)r   r   r   r   r   propertyr?   rB   rD   setterrH   rJ   rL   rM   rO   rP   rQ   rR   rV   r   r   r   r   r4   }   s<   













r4   c                       s   e Zd ZdZd1 fdd	Zdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zed$d%d& Zed$d'd( Zd2d)d*Zd+d, Zd-d. Zd/d0 Z  ZS )3FilterableStatementa  A statement to be used with filterable statements.

    Args:
        target (object): The target database object, it can be
                         :class:`mysqlx.Collection` or :class:`mysqlx.Table`.
        doc_based (Optional[bool]): `True` if it is document based
                                    (default: `True`).
        condition (Optional[str]): Sets the search condition to filter
                                   documents or records.
    TNc                    s   t t| j||d i | _i | _d | _d| _d | _d| _d | _	d| _
d | _d| _d | _d| _d | _d| _d| _d| _d| _d| _d| _d| _|r| | d S )Nr?   r@   r   r   F)superrY   r   _binding_map	_bindings_having_grouping_str	_grouping_limit_offset_limit_row_count_projection_str_projection_expr	_sort_str
_sort_expr
_where_str_where_exprhas_bindings	has_limithas_group_by
has_havinghas_projectionhas_sort	has_where
_set_wherer   r?   r@   	condition	__class__r   r   r      s2    zFilterableStatement.__init__c                 C   s   t |tr| t|  nt |tr8| |  nlt |trzt|}t |ts\tW n tk
rz   t	dY nX |
 D ]}| |||  qnt	ddS )a  Bind single object.

        Args:
            obj (:class:`mysqlx.DbDoc` or str): DbDoc or JSON string object.

        Raises:
            :class:`mysqlx.ProgrammingError`: If invalid JSON string to bind.
            ValueError: If JSON loaded is not a dictionary.
        zInvalid JSON string to bindz%Invalid JSON string or object to bindN)r   dictbindr   Zas_strstrjsonloads
ValueErrorr   keys)r   objreskeyr   r   r   _bind_single  s    





z FilterableStatement._bind_singlec                 G   s6   d| _ dt| | _t| j| j  | _d| _| S )zSets the sorting criteria.

        Args:
            *clauses: The expression strings defining the sort criteria.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.
        T,)	rn   r,   r   re   r   r6   Zparse_order_specrf   r;   r   Zclausesr   r   r   _sort%  s    	
zFilterableStatement._sortc                 C   sX   d| _ || _zt|| j }| | _W n tk
rD   tdY nX |j| _	d| _
| S )a  Sets the search condition to filter.

        Args:
            condition (str): Sets the search condition to filter documents or
                             records.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.
        TzInvalid condition)ro   rg   r   r6   r   rh   rz   r   Zplaceholder_name_to_positionr\   r;   )r   rr   r   r   r   r   rp   5  s    
zFilterableStatement._set_wherec                 G   s:   t | }d| _d|| _t| j| j  | _d| _dS )zJSet group by.

        Args:
            *fields: List of fields.
        Tr   N)	r   rk   r,   r_   r   r6   Zparse_expr_listr`   r;   r   fieldsr   r   r   _set_group_byJ  s    
z!FilterableStatement._set_group_byc                 C   s$   d| _ t|| j  | _d| _dS )zOSet having.

        Args:
            condition (str): The condition.
        TN)rl   r   r6   r   r^   r;   r   rr   r   r   r   _set_havingW  s    zFilterableStatement._set_havingc                 G   s:   t | }d| _d|| _t| j| j  | _d| _| S )zSet the projection.

        Args:
            *fields: List of fields.

        Returns:
            :class:`mysqlx.FilterableStatement`: Returns self.
        Tr   )	r   rm   r,   rc   r   r6   Zparse_table_select_projectionrd   r;   r   r   r   r   _set_projectiona  s    	
z#FilterableStatement._set_projectionc                 C   s   | j S zlReturns the binding map dictionary.

        Returns:
            dict: The binding map dictionary.
        r\   rA   r   r   r   get_binding_maps  s    z#FilterableStatement.get_binding_mapc                 C   s   | j S z\Returns the bindings list.

        Returns:
            `list`: The bindings list.
        r]   rA   r   r   r   get_bindings{  s    z FilterableStatement.get_bindingsc                 C   s   | j S )zrReturns the grouping expression list.

        Returns:
            `list`: The grouping expression list.
        )r`   rA   r   r   r   get_grouping  s    z FilterableStatement.get_groupingc                 C   s   | j S )zdReturns the having expression.

        Returns:
            object: The having expression.
        )r^   rA   r   r   r   
get_having  s    zFilterableStatement.get_havingc                 C   s   | j S )z]Returns the limit row count.

        Returns:
            int: The limit row count.
        )rb   rA   r   r   r   get_limit_row_count  s    z'FilterableStatement.get_limit_row_countc                 C   s   | j S )zWReturns the limit offset.

        Returns:
            int: The limit offset.
        )ra   rA   r   r   r   get_limit_offset  s    z$FilterableStatement.get_limit_offsetc                 C   s   | j S )zbReturns the where expression.

        Returns:
            object: The where expression.
        )rh   rA   r   r   r   get_where_expr  s    z"FilterableStatement.get_where_exprc                 C   s   | j S )zlReturns the projection expression.

        Returns:
            object: The projection expression.
        )rd   rA   r   r   r   get_projection_expr  s    z'FilterableStatement.get_projection_exprc                 C   s   | j S )z`Returns the sort expression.

        Returns:
            object: The sort expression.
        )rf   rA   r   r   r   get_sort_expr  s    z!FilterableStatement.get_sort_expr8.0.12c                 C   s
   |  |S )a&  Sets the search condition to filter.

        Args:
            condition (str): Sets the search condition to filter documents or
                             records.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.

        .. deprecated:: 8.0.12
        rp   r   r   r   r   where  s    zFilterableStatement.wherec                 G   s
   | j | S )zSets the sorting criteria.

        Args:
            *clauses: The expression strings defining the sort criteria.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.

        .. deprecated:: 8.0.12
        r   r   r   r   r   sort  s    zFilterableStatement.sortc                 C   sn   t |tr|dk rtd| jsBt| jdk| _t| jdk | _|| _d| _|rj| 	| t
jdtd | S )a  Sets the maximum number of items to be returned.

        Args:
            row_count (int): The maximum number of items.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.

        Raises:
            ValueError: If ``row_count`` is not a positive integer.

        .. versionchanged:: 8.0.12
           The usage of ``offset`` was deprecated.
        r   z0The 'row_count' value must be a positive integerTzh'limit(row_count, offset)' is deprecated, please use 'offset(offset)' to set the number of items to skip)category)r   intrz   rj   boolr:   r;   r=   rb   offsetwarningswarnDeprecationWarning)r   Z	row_countr   r   r   r   limit  s    
zFilterableStatement.limitc                 C   s$   t |tr|dk rtd|| _| S )a:  Sets the number of items to skip.

        Args:
            offset (int): The number of items to skip.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.

        Raises:
            ValueError: If ``offset`` is not a positive integer.

        .. versionadded:: 8.0.12
        r   z-The 'offset' value must be a positive integer)r   r   rz   ra   )r   r   r   r   r   r     s    zFilterableStatement.offsetc                 G   sN   d| _ t|}|dkr&| |d  n$|dkrB|d | j|d < ntd| S )a  Binds value(s) to a specific placeholder(s).

        Args:
            *args: The name of the placeholder and the value to bind.
                   A :class:`mysqlx.DbDoc` object or a JSON string
                   representation can be used.

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.

        Raises:
            ProgrammingError: If the number of arguments is invalid.
        Tr   r      #Invalid number of arguments to bind)ri   r   r   r]   r   )r   argscountr   r   r   rv   	  s    zFilterableStatement.bindc                 C   s   t dS rS   rT   rA   r   r   r   rV   !  s    zFilterableStatement.execute)TN)N)r   r   r   r   r   r   r   rp   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rv   rV   __classcell__r   r   rs   r   rY      s2   




rY   c                       sL   e Zd ZdZ fddZedd Zdd Zdd	 Zd
d Z	dd Z
  ZS )SqlStatementzA statement for SQL execution.

    Args:
        connection (mysqlx.connection.Connection): Connection object.
        sql (string): The sql statement to be executed.
    c                    s<   t t| jd dd || _|| _d | _g | _d| _d| _d S NFrZ   )	r[   r   r   r8   _sqlr\   r]   ri   rj   )r   
connectionsqlrs   r   r   r   1  s    zSqlStatement.__init__c                 C   s   | j S )zstring: The SQL text statement.)r   rA   r   r   r   r   :  s    zSqlStatement.sqlc                 C   s   | j S r   r   rA   r   r   r   r   ?  s    zSqlStatement.get_binding_mapc                 C   s   | j S r   r   rA   r   r   r   r   G  s    zSqlStatement.get_bindingsc                 G   sH   t |dkrtdd| _t| }t|ttfr8|| _n| j| | S )zBinds value(s) to a specific placeholder(s).

        Args:
            *args: The value(s) to bind.

        Returns:
            mysqlx.SqlStatement: SqlStatement object.
        r   r   T)	r   r   ri   r   r   r   r   r]   append)r   r   Zbindingsr   r   r   rv   O  s    	zSqlStatement.bindc                 C   s   | j | S )zaExecute the statement.

        Returns:
            mysqlx.SqlResult: SqlResult object.
        )r8   Zsend_sqlrA   r   r   r   rV   b  s    zSqlStatement.execute)r   r   r   r   r   rW   r   r   r   rv   rV   r   r   r   rs   r   r   *  s   	
r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )WriteStatementz/Provide common write operation attributes.
    c                    s   t t| || g | _d S r   )r[   r   r   _valuesr>   rs   r   r   r   n  s    zWriteStatement.__init__c                 C   s   | j S )z^Returns the list of values.

        Returns:
            `list`: The list of values.
        )r   rA   r   r   r   
get_valuesr  s    zWriteStatement.get_valuesc                 C   s   t dS rS   rT   rA   r   r   r   rV   z  s    zWriteStatement.execute)r   r   r   r   r   r   rV   r   r   r   rs   r   r   k  s   r   c                       sB   e Zd ZdZ fddZdd ZdddZd	d
 Zdd Z  Z	S )AddStatementzA statement for document addition on a collection.

    Args:
        collection (mysqlx.Collection): The Collection object.
    c                    s"   t t| |d d| _g | _d S )NTF)r[   r   r   _upsertids)r   
collectionrs   r   r   r     s    zAddStatement.__init__c                 C   s   | j S )zhReturns `True` if it's an upsert.

        Returns:
            bool: `True` if it's an upsert.
        r   rA   r   r   r   	is_upsert  s    zAddStatement.is_upsertTc                 C   s
   || _ | S )zSets the upset flag to the boolean of the value provided.
        Setting of this flag allows updating of the matched rows/documents
        with the provided value.

        Args:
            value (optional[bool]): Set or unset the upsert flag.
        r   rE   r   r   r   upsert  s    zAddStatement.upsertc                 G   s:   t | D ],}t|tr$| j| q| jt| q| S )zAdds a list of documents into a collection.

        Args:
            *values: The documents to be added into the collection.

        Returns:
            mysqlx.AddStatement: AddStatement object.
        )r   r   r   r   r   )r   r   valr   r   r   add  s
    	
zAddStatement.addc                 C   s    t | jdkrt S | j| S )[Execute the statement.

        Returns:
            mysqlx.Result: Result object.
        r   )r   r   r	   r8   send_insertrA   r   r   r   rV     s    zAddStatement.execute)T)
r   r   r   r   r   r   r   r   rV   r   r   r   rs   r   r     s   
r   c                   @   s"   e Zd ZdZdddZdd ZdS )
UpdateSpeczUpdate specification class implementation.

    Args:
        update_type (int): The update type.
        source (str): The source.
        value (Optional[str]): The value.
    Nc                 C   sj   |t dkr| || nL|| _|| _t|dkrL|d dkrL|dd  | _t| jd j| _|| _d S )N*Mysqlx.Crud.UpdateOperation.UpdateType.SETr   $r   F)	r
   
_table_setupdate_typesourcer   r   Zdocument_fieldr"   rF   )r   r   r   rF   r   r   r   r     s    zUpdateSpec.__init__c                 C   s$   t d| _t|d | _|| _dS )zlTable set.

        Args:
            source (str): The source.
            value (str): The value.
        r   TN)r
   r   r   Zparse_table_update_fieldr   rF   )r   r   rF   r   r   r   r     s
    zUpdateSpec._table_set)N)r   r   r   r   r   r   r   r   r   r   r     s   
r   c                       sp   e Zd ZdZ fddZdd Zdd Zdd	 Zed
dd Z	dd Z
dd Zdd Zdd Zdd Z  ZS )ModifyStatementaU  A statement for document update operations on a Collection.

    Args:
        collection (mysqlx.Collection): The Collection object.
        condition (str): Sets the search condition to identify the documents
                         to be modified.

    .. versionchanged:: 8.0.12
       The ``condition`` parameter is now mandatory.
    c                    s   t t| j||d i | _d S N)r?   rr   )r[   r   r   _update_opsr   r   rr   rs   r   r   r     s    zModifyStatement.__init__c                 G   s
   | j | S )zSets the sorting criteria.

        Args:
            *clauses: The expression strings defining the sort criteria.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.
        r   r   r   r   r   r     s    	zModifyStatement.sortc                 C   s   | j S ztReturns the list of update operations.

        Returns:
            `list`: The list of update operations.
        r   rA   r   r   r   get_update_ops  s    zModifyStatement.get_update_opsc                 C   s    t td||| j|< d| _| S )a2  Sets or updates attributes on documents in a collection.

        Args:
            doc_path (string): The document path of the item to be set.
            value (string): The value to be set on the specified attribute.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.
        z/Mysqlx.Crud.UpdateOperation.UpdateType.ITEM_SETTr   r
   r   r;   r   Zdoc_pathrF   r   r   r   set  s    
 
zModifyStatement.setr   c                 C   s    t td||| j|< d| _| S )a  Add an update to the statement setting the field, if it exists at
        the document path, to the given value.

        Args:
            doc_path (string): The document path of the item to be set.
            value (object): The value to be set on the specified attribute.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.

        .. deprecated:: 8.0.12
        z3Mysqlx.Crud.UpdateOperation.UpdateType.ITEM_REPLACETr   r   r   r   r   change  s     
zModifyStatement.changec                 G   s,   t | D ]}ttd|| j|< qd| _| S )a  Removes attributes from documents in a collection.

        Args:
            doc_paths (list): The list of document paths of the attributes to be
                              removed.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.
        z2Mysqlx.Crud.UpdateOperation.UpdateType.ITEM_REMOVET)r   r   r
   r   r;   )r   Z	doc_pathsitemr   r   r   unset&  s    
zModifyStatement.unsetc                 C   s    t td||| j|< d| _| S )a  Insert a value into the specified array in documents of a
        collection.

        Args:
            field (string): A document path that identifies the array attribute
                            and position where the value will be inserted.
            value (object): The value to be inserted.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.
        z3Mysqlx.Crud.UpdateOperation.UpdateType.ARRAY_INSERTTr   r   fieldrF   r   r   r   array_insert6  s     
zModifyStatement.array_insertc                 C   s    t td||| j|< d| _| S )a  Inserts a value into a specific position in an array attribute in
        documents of a collection.

        Args:
            doc_path (string): A document path that identifies the array
                               attribute and position where the value will be
                               inserted.
            value (object): The value to be inserted.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.
        z3Mysqlx.Crud.UpdateOperation.UpdateType.ARRAY_APPENDTr   r   r   r   r   array_appendH  s     
zModifyStatement.array_appendc                 C   sX   |dkrd}t |ttttfs&tdttddt |trB| n|| j	d< d| _
| S )a  Takes a :class:`mysqlx.DbDoc`, string JSON format or a dict with the
        changes and applies it on all matching documents.

        Args:
            doc (object): A generic document (DbDoc), string in JSON format or
                          dict, with the changes to apply to the matching
                          documents.

        Returns:
            mysqlx.ModifyStatement: ModifyStatement object.
        Nr   z>Invalid data for update operation on document collection tablez2Mysqlx.Crud.UpdateOperation.UpdateType.MERGE_PATCHpatchT)r   r   ru   r   rw   r   r   r
   r   r   r;   )r   docr   r   r   r   [  s     
zModifyStatement.patchc                 C   s   | j std| j| S )Execute the statement.

        Returns:
            mysqlx.Result: Result object.

        Raises:
            ProgrammingError: If condition was not set.
        z!No condition was found for modifyro   r   r8   Zsend_updaterA   r   r   r   rV   s  s    	zModifyStatement.execute)r   r   r   r   r   r   r   r   r   r   r   r   r   r   rV   r   r   r   rs   r   r     s   

r   c                       sz   e Zd ZdZd fdd	Zedd Zdd	 Zd
d Zdd Z	e
jfddZe
jfddZdd Zdd Zdd Z  ZS )ReadStatementa  Provide base functionality for Read operations

    Args:
        target (object): The target database object, it can be
                         :class:`mysqlx.Collection` or :class:`mysqlx.Table`.
        doc_based (Optional[bool]): `True` if it is document based
                                    (default: `True`).
        condition (Optional[str]): Sets the search condition to filter
                                   documents or records.
    TNc                    s,   t t| ||| d| _d| _tj| _d S NF)r[   r   r   _lock_exclusive_lock_sharedr   DEFAULT_lock_contentionrq   rs   r   r   r     s    zReadStatement.__init__c                 C   s   | j S )z::class:`mysqlx.LockContention`: The lock contention value.)r   rA   r   r   r   lock_contention  s    zReadStatement.lock_contentionc                 C   s6   zt |}W n tk
r*   tdY nX || _dS )zSet the lock contention.

        Args:
            lock_contention (:class:`mysqlx.LockContention`): Lock contention.

        Raises:
            ProgrammingError: If is an invalid lock contention value.
        z;Invalid lock contention mode. Use 'NOWAIT' or 'SKIP_LOCKED'N)r   indexrz   r   r   )r   r   _r   r   r   _set_lock_contention  s
    	z"ReadStatement._set_lock_contentionc                 C   s   | j S )zrReturns `True` if is `EXCLUSIVE LOCK`.

        Returns:
            bool: `True` if is `EXCLUSIVE LOCK`.
        )r   rA   r   r   r   is_lock_exclusive  s    zReadStatement.is_lock_exclusivec                 C   s   | j S )zlReturns `True` if is `SHARED LOCK`.

        Returns:
            bool: `True` if is `SHARED LOCK`.
        )r   rA   r   r   r   is_lock_shared  s    zReadStatement.is_lock_sharedc                 C   s   d| _ d| _| | | S )zExecute a read operation with `SHARED LOCK`. Only one lock can be
           active at a time.

        Args:
            lock_contention (:class:`mysqlx.LockContention`): Lock contention.
        FTr   r   r   r   r   r   r   r   lock_shared  s    
zReadStatement.lock_sharedc                 C   s   d| _ d| _| | | S )zExecute a read operation with `EXCLUSIVE LOCK`. Only one lock can be
           active at a time.

        Args:
            lock_contention (:class:`mysqlx.LockContention`): Lock contention.
        TFr   r   r   r   r   lock_exclusive  s    
zReadStatement.lock_exclusivec                 G   s   | j |  | S )zSets a grouping criteria for the resultset.

        Args:
            *fields: The string expressions identifying the grouping criteria.

        Returns:
            mysqlx.ReadStatement: ReadStatement object.
        )r   r   r   r   r   group_by  s    	
zReadStatement.group_byc                 C   s   |  | | S )a=  Sets a condition for records to be considered in agregate function
        operations.

        Args:
            condition (string): A condition on the agregate functions used on
                                the grouping criteria.

        Returns:
            mysqlx.ReadStatement: ReadStatement object.
        )r   r   r   r   r   having  s    
zReadStatement.havingc                 C   s   | j | S r   )r8   Z	send_findrA   r   r   r   rV     s    zReadStatement.execute)TN)r   r   r   r   r   rW   r   r   r   r   r   r   r   r   r   r   rV   r   r   r   rs   r   r     s   

r   c                       s2   e Zd ZdZd	 fdd	Zdd Zdd Z  ZS )
FindStatementa  A statement document selection on a Collection.

    Args:
        collection (mysqlx.Collection): The Collection object.
        condition (Optional[str]): An optional expression to identify the
                                   documents to be retrieved. If not specified
                                   all the documents will be included on the
                                   result unless a limit is set.
    Nc                    s   t t| |d| d S )NT)r[   r   r   r   rs   r   r   r     s    zFindStatement.__init__c                 G   s
   | j | S )zSets a document field filter.

        Args:
            *fields: The string expressions identifying the fields to be
                     extracted.

        Returns:
            mysqlx.FindStatement: FindStatement object.
        )r   r   r   r   r   r      s    
zFindStatement.fieldsc                 G   s
   | j | S zSets the sorting criteria.

        Args:
            *clauses: The expression strings defining the sort criteria.

        Returns:
            mysqlx.FindStatement: FindStatement object.
        r   r   r   r   r   r     s    	zFindStatement.sort)N)r   r   r   r   r   r   r   r   r   r   rs   r   r     s   	r   c                       s8   e Zd ZdZ fddZdd Zdd Zdd	 Z  ZS )
SelectStatementzA statement for record retrieval operations on a Table.

    Args:
        table (mysqlx.Table): The Table object.
        *fields: The fields to be retrieved.
    c                    s    t t| |d | j|  d S r   )r[   r   r   r   r   tabler   rs   r   r   r     s    zSelectStatement.__init__c                 C   s
   |  |S )zSets the search condition to filter.

        Args:
            condition (str): Sets the search condition to filter records.

        Returns:
            mysqlx.SelectStatement: SelectStatement object.
        r   r   r   r   r   r   #  s    	zSelectStatement.wherec                 G   s
   | j | S )zSets the order by criteria.

        Args:
            *clauses: The expression strings defining the order by criteria.

        Returns:
            mysqlx.SelectStatement: SelectStatement object.
        r   r   r   r   r   order_by.  s    	zSelectStatement.order_byc              
   C   s   | j rd| jnd}| jr(d| jnd}| jr>d| jnd}| jrTd| jnd}| j	rnd| j
| jnd}dj| jp~d| jj| jj|||||d	}|S )
zYReturns the generated SQL.

        Returns:
            str: The generated SQL.
        z
 WHERE {0}r   z GROUP BY {0}z HAVING {0}z ORDER BY {0}z LIMIT {0} OFFSET {1}zISELECT {select} FROM {schema}.{table}{where}{group}{having}{order}{limit}*)selectrB   r   r   r   groupr   order)ro   r%   rg   rk   r_   rl   r^   rn   re   rj   rb   ra   rc   rB   namer?   )r   r   r   r   r   r   Zstmtr   r   r   get_sql9  s4    
   zSelectStatement.get_sql)	r   r   r   r   r   r   r   r   r   r   r   rs   r   r     s
   r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )InsertStatementzA statement for insert operations on Table.

    Args:
        table (mysqlx.Table): The Table object.
        *fields: The fields to be inserted.
    c                    s    t t| |d t| | _d S r   )r[   r   r   r   _fieldsr   rs   r   r   r   X  s    zInsertStatement.__init__c                 G   s   | j tt|  | S )zSet the values to be inserted.

        Args:
            *values: The values of the columns to be inserted.

        Returns:
            mysqlx.InsertStatement: InsertStatement object.
        )r   r   r   r   )r   r   r   r   r   r   \  s    	zInsertStatement.valuesc                 C   s   | j | S r   )r8   r   rA   r   r   r   rV   h  s    zInsertStatement.execute)r   r   r   r   r   r   rV   r   r   r   rs   r   r   Q  s   r   c                       sH   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	  Z
S )UpdateStatementzA statement for record update operations on a Table.

    Args:
        table (mysqlx.Table): The Table object.

    .. versionchanged:: 8.0.12
       The ``fields`` parameters were removed.
    c                    s   t t| j|dd i | _d S r   )r[   r   r   r   r   r   rs   r   r   r   z  s    zUpdateStatement.__init__c                 C   s
   |  |S )zSets the search condition to filter.

        Args:
            condition (str): Sets the search condition to filter records.

        Returns:
            mysqlx.UpdateStatement: UpdateStatement object.
        r   r   r   r   r   r   ~  s    	zUpdateStatement.wherec                 G   s
   | j | S )zSets the order by criteria.

        Args:
            *clauses: The expression strings defining the order by criteria.

        Returns:
            mysqlx.UpdateStatement: UpdateStatement object.
        r   r   r   r   r   r     s    	zUpdateStatement.order_byc                 C   s   | j S r   r   rA   r   r   r   r     s    zUpdateStatement.get_update_opsc                 C   s    t td||| j|< d| _| S )a  Updates the column value on records in a table.

        Args:
            field (string): The column name to be updated.
            value (object): The value to be set on the specified column.

        Returns:
            mysqlx.UpdateStatement: UpdateStatement object.
        r   Tr   r   r   r   r   r     s    
 
zUpdateStatement.setc                 C   s   | j std| j| S )zExecute the statement.

        Returns:
            mysqlx.Result: Result object

        Raises:
            ProgrammingError: If condition was not set.
        z!No condition was found for updater   rA   r   r   r   rV     s    	zUpdateStatement.execute)r   r   r   r   r   r   r   r   r   rV   r   r   r   rs   r   r   q  s   r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )RemoveStatementaE  A statement for document removal from a collection.

    Args:
        collection (mysqlx.Collection): The Collection object.
        condition (str): Sets the search condition to identify the documents
                         to be removed.

    .. versionchanged:: 8.0.12
       The ``condition`` parameter was added.
    c                    s   t t| j||d d S r   )r[   r   r   r   rs   r   r   r     s    zRemoveStatement.__init__c                 G   s
   | j | S r   r   r   r   r   r   r     s    	zRemoveStatement.sortc                 C   s   | j std| j| S )r   z!No condition was found for removero   r   r8   Zsend_deleterA   r   r   r   rV     s    	zRemoveStatement.execute)r   r   r   r   r   r   rV   r   r   r   rs   r   r     s   
r   c                       s8   e Zd ZdZ fddZdd Zdd Zdd	 Z  ZS )
DeleteStatementzA statement that drops a table.

    Args:
        table (mysqlx.Table): The Table object.

    .. versionchanged:: 8.0.12
       The ``condition`` parameter was removed.
    c                    s   t t| j|dd d S r   )r[   r   r   r   rs   r   r   r     s    zDeleteStatement.__init__c                 C   s
   |  |S )zSets the search condition to filter.

        Args:
            condition (str): Sets the search condition to filter records.

        Returns:
            mysqlx.DeleteStatement: DeleteStatement object.
        r   r   r   r   r   r     s    	zDeleteStatement.wherec                 G   s
   | j | S )zSets the order by criteria.

        Args:
            *clauses: The expression strings defining the order by criteria.

        Returns:
            mysqlx.DeleteStatement: DeleteStatement object.
        r   r   r   r   r   r     s    	zDeleteStatement.order_byc                 C   s   | j std| j| S )r   z!No condition was found for deleter   rA   r   r   r   rV     s    	zDeleteStatement.execute)	r   r   r   r   r   r   r   rV   r   r   r   rs   r   r     s
   r   c                       s(   e Zd ZdZ fddZdd Z  ZS )CreateCollectionIndexStatementa)  A statement that creates an index on a collection.

    Args:
        collection (mysqlx.Collection): Collection.
        index_name (string): Index name.
        index_desc (dict): A dictionary containing the fields members that
                           constraints the index to be created. It must have
                           the form as shown in the following::

                               {"fields": [{"field": member_path,
                                            "type": member_type,
                                            "required": member_required,
                                            "collation": collation,
                                            "options": options,
                                            "srid": srid},
                                            # {... more members,
                                            #      repeated as many times
                                            #      as needed}
                                            ],
                                "type": type}
    c                    s8   t t| j|d t|| _|| _| jdg | _d S )N)r?   r   )	r[   r   r   copydeepcopy_index_desc_index_namepop_fields_desc)r   r   Z
index_nameZ
index_descrs   r   r   r   '  s    z'CreateCollectionIndexStatement.__init__c              
   C   sP  | j dkrtt| j z`t| j   }t|trZ|d t	dkrxtt| j n|j
t	dkrxtt| j W n( ttfk
r   tt| j Y nX | jstd| jt| jtstdi }| j |d< | jj|d< | jjj|d< d| jkr| jd|d< nd	|d< | jd
d|d
< |d
 r@tdg |d< | jr`td| jz| jD ]v}i }|d|d< |d|d< |dd|d< |dd|d< t|d tstdt|d tstd|d  dkr|d std|d  d	kr,|d dkr,tdd|krn|d  ds`td|d  |d|d< d|kr|d  dkrtd|d|d< d|kr|d  dkrtd|d|d< |d | qjW n4 tk
r } ztd ||W 5 d}~X Y nX | jD ]}|r"td!|q"| jd"d#d$|S )%r   NtypezMysqlx.Expr.Expr.Type.IDENTzERequired member 'fields' not found in the given index description: {}z-Required member 'fields' must contain a list.r   r   rB   ZINDEXuniqueFz!Unique indexes are not supported.
constraintzUnidentified fields: {}r   memberrequiredarrayz'Field member 'required' must be Booleanz$Field member 'array' must be BooleanZSPATIALzQField member 'required' must be set to 'True' when index type is set to 'SPATIAL'ZGEOJSONzIIndex 'type' must be set to 'SPATIAL' when field type is set to 'GEOJSON'Z	collationZTEXTzFThe 'collation' member can only be used when field type is set to '{}'optionszIThe 'options' member can only be used when index type is set to 'GEOJSON'ZsridzFThe 'srid' member can only be used when index type is set to 'GEOJSON'z4Required inner member {} not found in constraint: {}zUnidentified inner fields:{}ZmysqlxZcreate_collection_indexT)r  r   ERR_INVALID_INDEX_NAMEr%   r   r   Zget_messager   ru   r
   r  rz   AttributeErrorr  r   r   r5   r   rB   r  r   r   	TypeErrorupper
startswithr   KeyErrorr8   Zexecute_nonquery)r   Zparsed_identr   Z
field_descr  errr   r   r   rV   -  s    













 

   z&CreateCollectionIndexStatement.execute)r   r   r   r   r   rV   r   r   r   rs   r   r     s   r   )r   )r   )r   )r   )*r   r   rx   r   errorsr   r   r   r   	constantsr   Zdbdocr   Zhelpersr   resultr	   Zprotobufr
   r  objectr   r   r$   r'   r-   r3   r4   rY   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sF   



i  FA:" #r%9 H(0