U
    ec                     @   s  d Z ddlZddlZddlZddlmZ ddlm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ZG dd dZdd Zd7ddZd8ddZd9ddZd:ddZG 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$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   )LockContention)DbDoc)NotSupportedErrorProgrammingError)
ExprParser)
deprecated)mysqlxpb_enum)Resultz&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-ix8dg7li/mysqlx/statement.py__init__1   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_params5   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   sH   t | dkrdS d|kr0| dd}d| dS | d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   r    z""r   )r   replace)r!   r"   quotedr   r   r   quote_identifierM   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>l   s     z.quote_multipart_identifier.<locals>.<listcomp>)join)Zidentifiersr"   r   r)   r   quote_multipart_identifiera   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   r'   r   r   r   )splitr   strip)Zdefault_schemaZ
table_namer"   quote	delimitertempr   r   r   parse_table_namep   s    r2   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.)r4   r   r   r   r   r>      s    zStatement.targetc                 C   s   | j jS )z*:class:`mysqlx.Schema`: The Schema object.)r4   schemar@   r   r   r   rA      s    zStatement.schemac                 C   s   | j S )zXReturns this statement ID.

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

        Returns:
            bool: `True` if it is document based.
        )r5   r@   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   NrF   r@   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   NrF   r@   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NotImplementedErrorr@   r   r   r   execute   s    zStatement.executeN)T)r   r   r   r   r   propertyr>   rA   rC   setterrG   rI   rK   rL   rN   rO   rP   rQ   rU   r   r   r   r   r3      s<   













r3   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  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)superr   _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      s.    zFilterableStatement.__init__c              
   C   s   t |tr| t|  nt |tr8| |  n|t |trzt|}t |ts\tW n, tk
r } zt	d|W 5 d}~X 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 bindNz%Invalid JSON string or object to bind)r   dictbindr   Zas_strstrjsonloads
ValueErrorr   keys)r   objreserr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,)	rm   r+   r   rd   r   r5   Zparse_order_specre   r:   r   Zclausesr   r   r   _sort+  s    	 
zFilterableStatement._sortc              
   C   sh   d| _ || _zt|| j }| | _W n, tk
rT } ztd|W 5 d}~X 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 conditionN)rn   rf   r   r5   r   rg   ry   r   Zplaceholder_name_to_positionr[   r:   )r   rq   r   r}   r   r   r   ro   <  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   rj   r+   r^   r   r5   Zparse_expr_listr_   r:   r   fieldsr   r   r   _set_group_byQ  s     
z!FilterableStatement._set_group_byc                 C   s$   d| _ t|| j  | _d| _dS )zOSet having.

        Args:
            condition (str): The condition.
        TN)rk   r   r5   r   r]   r:   r   rq   r   r   r   _set_having_  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   rl   r+   rb   r   r5   Zparse_table_select_projectionrc   r:   r   r   r   r   _set_projectioni  s    	 
z#FilterableStatement._set_projectionc                 C   s   | j S zlReturns the binding map dictionary.

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

        Returns:
            `list`: The bindings list.
        r\   r@   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_   r@   r   r   r   get_grouping  s    z FilterableStatement.get_groupingc                 C   s   | j S )zdReturns the having expression.

        Returns:
            object: The having expression.
        )r]   r@   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.
        )ra   r@   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.
        )r`   r@   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.
        )rg   r@   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.
        )rc   r@   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.
        )re   r@   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
        ro   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   intry   ri   boolr9   r:   r<   ra   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   ry   r`   )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)rh   r   r   r\   r   )r   argscountr   r   r   ru     s    zFilterableStatement.bindc                 C   s   t dS rR   rS   r@   r   r   r   rU   ,  s    zFilterableStatement.execute)TN)N)r   r   r   r   r   r   r   ro   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ru   rU   __classcell__r   r   rr   r   rX      s2   



!rX   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                    s8   t  jd dd || _|| _d | _g | _d| _d| _d S NFrY   )rZ   r   r7   _sqlr[   r\   rh   ri   )r   
connectionsqlrr   r   r   r   =  s    zSqlStatement.__init__c                 C   s   | j S )zstring: The SQL text statement.)r   r@   r   r   r   r   F  s    zSqlStatement.sqlc                 C   s   | j S r   r   r@   r   r   r   r   K  s    zSqlStatement.get_binding_mapc                 C   s   | j S r   r   r@   r   r   r   r   S  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   rh   r   r   r   r   r\   append)r   r   bindingsr   r   r   ru   [  s    	zSqlStatement.bindc                 C   s   | j | S )zaExecute the statement.

        Returns:
            mysqlx.SqlResult: SqlResult object.
        )r7   Zsend_sqlr@   r   r   r   rU   n  s    zSqlStatement.execute)r   r   r   r   r   rV   r   r   r   ru   rU   r   r   r   rr   r   r   5  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  || g | _d S r   )rZ   r   _valuesr=   rr   r   r   r   z  s    zWriteStatement.__init__c                 C   s   | j S )z^Returns the list of values.

        Returns:
            `list`: The list of values.
        )r   r@   r   r   r   
get_values~  s    zWriteStatement.get_valuesc                 C   s   t dS rR   rS   r@   r   r   r   rU     s    zWriteStatement.execute)r   r   r   r   r   r   rU   r   r   r   rr   r   r   w  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  |d d| _g | _d S )NTF)rZ   r   _upsertids)r   
collectionrr   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   r@   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   rD   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
   r7   send_insertr@   r   r   r   rU     s    zAddStatement.execute)T)
r   r   r   r   r   r   r   r   rU   r   r   r   rr   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.

    Raises:
        ProgrammingError: If `source` is invalid.
    Nc              
   C   sp   |t dkr| || nR|| _zt|d j| _W n. tk
rd } zt| |W 5 d }~X Y nX || _	d S )N*Mysqlx.Crud.UpdateOperation.UpdateType.SETF)
r	   
_table_setupdate_typer   Zdocument_fieldr!   sourcery   r   rE   )r   r   r   rE   r}   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   rE   )r   r   rE   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  j||d i | _d S N)r>   rq   rZ   r   _update_opsr   r   rq   rr   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   r@   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_pathrE   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   unset8  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   fieldrE   r   r   r   array_insertJ  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_append^  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   rt   r   rv   r   r   r	   r   r   r:   )r   docr   r   r   r   s  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rn   r   r7   Zsend_updater@   r   r   r   rU     s    	zModifyStatement.execute)r   r   r   r   r   r   r   r   r   r   r   r   r   r   rU   r   r   r   rr   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  ||| d| _d| _tj| _d S NF)rZ   r   _lock_exclusive_lock_sharedr   DEFAULT_lock_contentionrp   rr   r   r   r     s    zReadStatement.__init__c                 C   s   | j S )z::class:`mysqlx.LockContention`: The lock contention value.)r   r@   r   r   r   lock_contention  s    zReadStatement.lock_contentionc              
   C   sF   zt |j}W n, tk
r: } ztd|W 5 d}~X 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   rE   ry   r   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   r@   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   r@   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   )r7   Z	send_findr@   r   r   r   rU     s    zReadStatement.execute)TN)r   r   r   r   r   rV   r   r   r   r   r   r   r   r   r   r   rU   r   r   r   rr   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  |d| d S )NTrZ   r   r   rr   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   rr   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  |d | j|  d S r   )rZ   r   r   r   tabler   rr   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   A  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_byL  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rrd| j	 d| j
 nd}d| jpd	 d
| jj d| jj | | | | | }|S )zYReturns the generated SQL.

        Returns:
            str: The generated SQL.
        z WHERE r   z
 GROUP BY z HAVING z
 ORDER BY z LIMIT z OFFSET zSELECT *z FROM r'   )rn   rf   rj   r^   rk   r]   rm   rd   ri   ra   r`   rb   rA   namer>   )r   r   r   r   r   r   Zstmtr   r   r   get_sqlW  s    6zSelectStatement.get_sql)	r   r   r   r   r   r   r   r   r   r   r   rr   r   r   5  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  |d t| | _d S r   )rZ   r   r   _fieldsr   rr   r   r   r   v  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   z  s    	zInsertStatement.valuesc                 C   s   | j | S r   )r7   r   r@   r   r   r   rU     s    zInsertStatement.execute)r   r   r   r   r   r   rU   r   r   r   rr   r   r   n  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  j|dd i | _d S r   r   r   r   rr   r   r   r     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   r@   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   r@   r   r   r   rU     s    	zUpdateStatement.execute)r   r   r   r   r   r   r   r   r   rU   r   r   r   rr   r   r     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  j||d d S r   r   r   rr   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rn   r   r7   Zsend_deleter@   r   r   r   rU     s    	zRemoveStatement.execute)r   r   r   r   r   r   rU   r   r   r   rr   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  j|dd d S r   r   r   rr   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   r@   r   r   r   rU   &  s    	zDeleteStatement.execute)	r   r   r   r   r   r   r   rU   r   r   r   rr   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                    s4   t  j|d t|| _|| _| jdg | _d S )N)r>   r   )rZ   r   copydeepcopy_index_desc_index_namepop_fields_desc)r   r   Z
index_nameZ
index_descrr   r   r   r   K  s    z'CreateCollectionIndexStatement.__init__c              
   C   sh  | 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 n8 ttfk
r } ztt| j |W 5 d}~X 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
 rPtdg |d< | jrptd| j z| jD ]x}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r|d  dsrtd|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 | qzW n: tk
r2 } ztd!| 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.IDENTzCRequired member 'fields' not found in the given index description: z,Required member 'fields' must contain a listr   r   rA   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TEXTzCThe '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'zRequired inner member z not found in constraint: zUnidentified inner fields: ZmysqlxZcreate_collection_indexT)r   r   ERR_INVALID_INDEX_NAMEformatr   r   Zget_messager   rt   r	   r  ry   AttributeErrorr  r   r   r4   r   rA   r  r   r   	TypeErrorupper
startswithr   KeyErrorr7   Zexecute_nonquery)r   Zparsed_identr}   r   Z
field_descr  r   r   r   rU   Q  s    







 



   z&CreateCollectionIndexStatement.execute)r   r   r   r   r   rU   r   r   r   rr   r   r   4  s   r   )r   )r   )r   )r   ))r   r   rw   r   	constantsr   Zdbdocr   errorsr   r   r   r   Zhelpersr   Zprotobufr	   resultr
   r  r   r   r#   r&   r,   r2   r3   rX   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sF   



h  KB;# /t&9!L(1