3
S^Ͷ                 @   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
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d8ddZd9ddZd:d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 d0d1 d1eZ)G d2d3 d3eZ*G d4d5 d5eZ+G d6d7 d7eZ,dS )<zImplementation of Statements.    N   )ProgrammingErrorNotSupportedError)
ExprParser)	INT_TYPESSTRING_TYPES)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   B/tmp/pip-build-8app2_gc/mysql-connector-python/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   "r!   r!   r   )
identifiersql_moder   r   r   is_quoted_identifier<   s    
r$   c             C   s<   t | dkrdS d|kr*dj| jddS dj| j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replace)r"   r#   r   r   r   quote_identifierL   s
    r'   c                s   dj  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>h   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j |nd}|j|d}t|dkrB| n|d j||d j|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_namel   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|j 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   schema)r   r   r   r   r?      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 )N)r8   )r   valuer   r   r   r@      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 )N)r:   )r   rA   r   r   r   rC      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 )N)r;   )r   rA   r   r   r   rD      s    c             C   s
   | j dkS )zDbool: `True` if this statement was executed more than once.
        r   )r9   )r   r   r   r   repeated   s    zStatement.repeatedc             C   s   | j S )zBbool: `True` to deallocate + prepare + execute statement.
        )r<   )r   r   r   r   deallocate_prepare_execute   s    z$Statement.deallocate_prepare_executec             C   s
   || _ d S )N)r<   )r   rA   r   r   r   rF      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   N)r9   )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   N)r9   )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)NotImplementedError)r   r   r   r   execute   s    zStatement.executeN)T)r   r   r   r   r   propertyr=   r?   r@   setterrB   rC   rD   rE   rF   rG   rH   rI   rK   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 t| j||d i | _i | _d | _d| _d | _d| _d | _	d| _
d | _d| _d | _d| _d | _d| _d| _d| _d| _d| _d| _d| _|r| j| d S )N)r=   r>   r   r   F)superrN   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      s0    zFilterableStatement.__init__c             C   s   t |tr| jt|j  nt |tr8| j|j  npt |trytj|}t |ts\tW n tk
rz   t	dY nX x*|j
 D ]}| j|||  qW n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_strr   jsonloads
ValueErrorr   keys)r   objreskeyr   r   r   _bind_single  s    

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

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

        Returns:
            mysqlx.FilterableStatement: FilterableStatement object.
        T,)	rb   r+   r   rY   r   r5   Zparse_order_specrZ   r:   )r   clausesr   r   r   _sort&  s    	zFilterableStatement._sortc             C   sX   d| _ || _yt|| j }|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)rc   r[   r   r5   r   r\   rk   r   Zplaceholder_name_to_positionrP   r:   )r   re   r   r   r   r   rd   6  s    
zFilterableStatement._set_wherec             G   s:   t | }d| _dj|| _t| j| j j | _d| _dS )zJSet group by.

        Args:
            *fields: List of fields.
        Trq   N)	r   r_   r+   rS   r   r5   Zparse_expr_listrT   r:   )r   fieldsr   r   r   _set_group_byK  s    z!FilterableStatement._set_group_byc             C   s$   d| _ t|| j j | _d| _dS )zOSet having.

        Args:
            condition (str): The condition.
        TN)r`   r   r5   r   rR   r:   )r   re   r   r   r   _set_havingX  s    zFilterableStatement._set_havingc             G   s:   t | }d| _dj|| _t| j| j j | _d| _| S )zSet the projection.

        Args:
            *fields: List of fields.

        Returns:
            :class:`mysqlx.FilterableStatement`: Returns self.
        Trq   )	r   ra   r+   rW   r   r5   Zparse_table_select_projectionrX   r:   )r   rt   r   r   r   _set_projectionb  s    	z#FilterableStatement._set_projectionc             C   s   | j S )zlReturns the binding map dictionary.

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

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

        Returns:
            object: The having expression.
        )rR   )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.
        )rV   )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.
        )rU   )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.
        )r\   )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.
        )rX   )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.
        )rZ   )r   r   r   r   get_sort_expr  s    z!FilterableStatement.get_sort_exprz8.0.12c             C   s
   | j |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
        )rd   )r   re   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
        )rs   )r   rr   r   r   r   sort  s    zFilterableStatement.sortc             C   sp   t |t s|dk rtd| jsDt| jdk| _t| jdk | _|| _d| _|rl| j	| 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   r   rk   r^   boolr9   r:   r<   rV   offsetwarningswarnDeprecationWarning)r   Z	row_countr   r   r   r   limit  s    
zFilterableStatement.limitc             C   s&   t |t s|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   rk   rU   )r   r   r   r   r   r     s    zFilterableStatement.offsetc             G   sN   d| _ t|}|dkr&| j|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      z#Invalid number of arguments to bind)r]   r   rp   rQ   r   )r   argscountr   r   r   rh   
  s    zFilterableStatement.bindc             C   s   t dS )zqExecute the statement.

        Raises:
           NotImplementedError: This method must be implemented.
        N)rJ   )r   r   r   r   rK   "  s    zFilterableStatement.execute)TN)N)r   r   r   r   r   rp   rs   rd   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r
   r   r   r   r   rh   rK   __classcell__r   r   )rf   r   rN      s.   


rN   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 )NF)r=   r>   )	rO   r   r   r7   _sqlrP   rQ   r]   r^   )r   
connectionsql)rf   r   r   r   2  s    zSqlStatement.__init__c             C   s   | j S )zstring: The SQL text statement.)r   )r   r   r   r   r   ;  s    zSqlStatement.sqlc             C   s   | j S )zlReturns the binding map dictionary.

        Returns:
            dict: The binding map dictionary.
        )rP   )r   r   r   r   rx   @  s    zSqlStatement.get_binding_mapc             C   s   | j S )z\Returns the bindings list.

        Returns:
            `list`: The bindings list.
        )rQ   )r   r   r   r   ry   H  s    zSqlStatement.get_bindingsc             G   sH   t |dkrtdd| _t| }t|ttfr8|| _n| jj| | S )zBinds value(s) to a specific placeholder(s).

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

        Returns:
            mysqlx.SqlStatement: SqlStatement object.
        r   z#Invalid number of arguments to bindT)	r   r   r]   r   r   r   r   rQ   append)r   r   Zbindingsr   r   r   rh   P  s    	zSqlStatement.bindc             C   s   | j j| S )zaExecute the statement.

        Returns:
            mysqlx.SqlResult: SqlResult object.
        )r7   Zsend_sql)r   r   r   r   rK   c  s    zSqlStatement.execute)r   r   r   r   r   rL   r   rx   ry   rh   rK   r   r   r   )rf   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| j|| g | _d S )N)rO   r   r   _values)r   r=   r>   )rf   r   r   r   o  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_valuess  s    zWriteStatement.get_valuesc             C   s   t dS )zqExecute the statement.

        Raises:
           NotImplementedError: This method must be implemented.
        N)rJ   )r   r   r   r   rK   {  s    zWriteStatement.execute)r   r   r   r   r   r   rK   r   r   r   )rf   r   r   l  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| j|d d| _g | _d S )NTF)rO   r   r   _upsertids)r   
collection)rf   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   )r   rA   r   r   r   upsert  s    zAddStatement.upsertc             G   s>   x8t | D ],}t|tr&| jj| q
| jjt| q
W | 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j| S )z[Execute the statement.

        Returns:
            mysqlx.Result: Result object.
        r   )r   r   r   r7   send_insert)r   r   r   r   rK     s    zAddStatement.execute)T)
r   r   r   r   r   r   r   r   rK   r   r   r   )rf   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| j|| nL|| _|| _t|dkrL|d dkrL|dd  | _t| jdj j| _|| _d S )Nz*Mysqlx.Crud.UpdateOperation.UpdateType.SETr   $r   F)	r   
_table_setupdate_typesourcer   r   Zdocument_fieldr"   rA   )r   r   r   rA   r   r   r   r     s    zUpdateSpec.__init__c             C   s$   t d| _t|dj | _|| _dS )zlTable set.

        Args:
            source (str): The source.
            value (str): The value.
        z*Mysqlx.Crud.UpdateOperation.UpdateType.SETTN)r   r   r   Zparse_table_update_fieldr   rA   )r   r   rA   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=   re   )rO   r   r   _update_ops)r   r   re   )rf   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.
        )rs   )r   rr   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   doc_pathrA   r   r   r   set  s
    
zModifyStatement.setz8.0.12c             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_REPLACET)r   r   r   r:   )r   r   rA   r   r   r   change  s
    zModifyStatement.changec             G   s0   x$t | D ]}ttd|| j|< q
W 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_INSERTT)r   r   r   r:   )r   fieldrA   r   r   r   array_insert7  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_APPENDT)r   r   r   r:   )r   r   rA   r   r   r   array_appendI  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|j 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   rg   r	   strr   r   r   r   r   r:   )r   docr   r   r   r   \  s     zModifyStatement.patchc             C   s   | j std| jj| S )zExecute the statement.

        Returns:
            mysqlx.Result: Result object.

        Raises:
            ProgrammingError: If condition was not set.
        z!No condition was found for modify)rc   r   r7   send_update)r   r   r   r   rK   t  s    	zModifyStatement.execute)r   r   r   r   r   r   r   r   r
   r   r   r   r   r   rK   r   r   r   )rf   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| j||| d| _d| _tj| _d S )NF)rO   r   r   _lock_exclusive_lock_sharedr   DEFAULT_lock_contention)r   r=   r>   re   )rf   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   s6   yt j|}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   indexrk   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| _| j| | 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| _| j| | 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.
        TF)r   r   r   )r   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.
        )ru   )r   rt   r   r   r   group_by  s    	
zReadStatement.group_byc             C   s   | j | | 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.
        )rv   )r   re   r   r   r   having  s    
zReadStatement.havingc             C   s   | j j| S )z[Execute the statement.

        Returns:
            mysqlx.Result: Result object.
        )r7   Z	send_find)r   r   r   r   rK     s    zReadStatement.execute)TN)r   r   r   r   r   rL   r   r   r   r   r   r   r   r   r   r   rK   r   r   r   )rf   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| j|d| d S )NT)rO   r   r   )r   r   re   )rf   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.
        )rw   )r   rt   r   r   r   rt     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.
        )rs   )r   rr   r   r   r   r     s    	zFindStatement.sort)N)r   r   r   r   r   rt   r   r   r   r   )rf   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| j|d | j|  d S )NF)rO   r   r   rw   )r   tablert   )rf   r   r   r      s    zSelectStatement.__init__c             C   s
   | j |S )zSets the search condition to filter.

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

        Returns:
            mysqlx.SelectStatement: SelectStatement object.
        )rd   )r   re   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.
        )rs   )r   rr   r   r   r   order_by/  s    	zSelectStatement.order_byc          
   C   s   | j rdj| jnd}| jr(dj| jnd}| jr>dj| jnd}| jrTdj| jnd}| j	rndj| 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}*)selectr?   r   r   r   groupr   order)rc   r%   r[   r_   rS   r`   rR   rb   rY   r^   rV   rU   rW   r?   namer=   )r   r   r   r   r   r   stmtr   r   r   get_sql:  s    
zSelectStatement.get_sql)	r   r   r   r   r   r   r   r   r   r   r   )rf   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| j|d t| | _d S )NF)rO   r   r   r   _fields)r   r   rt   )rf   r   r   r   Y  s    zInsertStatement.__init__c             G   s   | j 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 j| S )z[Execute the statement.

        Returns:
            mysqlx.Result: Result object.
        )r7   r   )r   r   r   r   rK   i  s    zInsertStatement.execute)r   r   r   r   r   r   rK   r   r   r   )rf   r   r   R  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 )NF)r=   r>   )rO   r   r   r   )r   r   )rf   r   r   r   {  s    zUpdateStatement.__init__c             C   s
   | j |S )zSets the search condition to filter.

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

        Returns:
            mysqlx.UpdateStatement: UpdateStatement object.
        )rd   )r   re   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.
        )rs   )r   rr   r   r   r   r     s    	zUpdateStatement.order_byc             C   s   | j S )ztReturns the list of update operations.

        Returns:
            `list`: The list of update operations.
        )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.
        z*Mysqlx.Crud.UpdateOperation.UpdateType.SETT)r   r   r   r:   )r   r   rA   r   r   r   r     s    
zUpdateStatement.setc             C   s   | j std| jj| S )zExecute the statement.

        Returns:
            mysqlx.Result: Result object

        Raises:
            ProgrammingError: If condition was not set.
        z!No condition was found for update)rc   r   r7   r   )r   r   r   r   rK     s    	zUpdateStatement.execute)r   r   r   r   r   r   r   r   r   rK   r   r   r   )rf   r   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 t| j||d d S )N)r=   re   )rO   r   r   )r   r   re   )rf   r   r   r     s    zRemoveStatement.__init__c             G   s
   | j | S )zSets the sorting criteria.

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

        Returns:
            mysqlx.FindStatement: FindStatement object.
        )rs   )r   rr   r   r   r   r     s    	zRemoveStatement.sortc             C   s   | j std| jj| S )zExecute the statement.

        Returns:
            mysqlx.Result: Result object.

        Raises:
            ProgrammingError: If condition was not set.
        z!No condition was found for remove)rc   r   r7   send_delete)r   r   r   r   rK     s    	zRemoveStatement.execute)r   r   r   r   r   r   rK   r   r   r   )rf   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 )NF)r=   r>   )rO   r   r   )r   r   )rf   r   r   r     s    zDeleteStatement.__init__c             C   s
   | j |S )zSets the search condition to filter.

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

        Returns:
            mysqlx.DeleteStatement: DeleteStatement object.
        )rd   )r   re   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.
        )rs   )r   rr   r   r   r   r     s    	zDeleteStatement.order_byc             C   s   | j std| jj| S )zExecute the statement.

        Returns:
            mysqlx.Result: Result object.

        Raises:
            ProgrammingError: If condition was not set.
        z!No condition was found for delete)rc   r   r7   r   )r   r   r   r   rK     s    	zDeleteStatement.execute)	r   r   r   r   r   r   r   rK   r   r   r   )rf   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|| _|| _| jjdg | _d S )N)r=   rt   )	rO   r   r   copydeepcopy_index_desc_index_namepop_fields_desc)r   r   Z
index_nameZ
index_desc)rf   r   r   r   (  s    z'CreateCollectionIndexStatement.__init__c             C   sT  | j dkrttj| j y`t| j j j }t|trZ|d t	dkrxttj| j n|j
t	dkrxttj| j W n( ttfk
r   ttj| j Y nX | jstdj| jt| jtstdi }| j |d< | jj|d< | jjj|d< d| jkr| jjd|d< nd	|d< | jjd
d|d
< |d
 r@tdg |d< | jr`tdj| jyx|| jD ]p}i }|jd|d< |jd|d< |jdd|d< |jdd|d< t|d tstdt|d tstd|d j dkr
|d  r
td|d j d	kr2|d dkr2tdd|krh|d j jdsZtdn|jd|d< d|kr|d j dkrtdn|jd|d< d|kr|d j dkrtdn|jd|d< |d j| qnW W n4 tk
r } ztd j||W Y dd}~X nX x$| jD ]}|r$td!j|q$W | jjd"d#d$|S )%z[Execute the statement.

        Returns:
            mysqlx.Result: Result object.
        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   r?   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TEXTzLThe 'collation' member can only be used when field  type is set to 'GEOJSON'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   rg   r   r   rk   AttributeErrorr   r   r   r4   r   r?   r   r   r   	TypeErrorupper
startswithr   KeyErrorr7   Zexecute_nonquery)r   Zparsed_identr   Z
field_descr   errr   r   r   rK   .  s    








z&CreateCollectionIndexStatement.execute)r   r   r   r   r   rK   r   r   r   )rf   r   r     s   r   )r   )r   )r   )r   )-r   r   ri   r   errorsr   r   r   r   compatr   r   	constantsr   Zdbdocr	   helpersr
   resultr   Zprotobufr   r   objectr   r   r$   r'   r,   r2   r3   rN   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sH   



i  FA:" #r%9 H(0