
    &                         d Z ddlmZ ddlmZ ddlm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 dd	lmZ ddlZdd
lmZ ddlZd ZddZ G d dej(                        Z G d de
j,                        Zy)znA persistent cache implementation using sqlite3.

See the persistent_cache module for a detailed description.
    )absolute_import)division)unicode_literalsN)
exceptions)metadata_table)persistent_cache_base)files)rangec                 &    dj                  |       S )zReturns a field reference name.

  Args:
    column: The field column number counting from 0.

  Returns:
    A field reference name.
  z	f{column}column)formatr   s    -lib/googlecloudsdk/core/cache/sqlite_cache.py	_FieldRefr   '   s     
		6		**    c                    g }| rt        t        |             D ]  }| |   }|t        |t        j                        r^|j                  dd      j                  dd      j                  dd      }|j                  dj                  t        |      |             |j                  d	j                  t        |      |
              |syddj                  |      z   S )aZ  Returns a WHERE clause for the row template.

  Column string matching supports * and ? match ops.

  Args:
    row_template: A template row tuple. A column value None means match all
      values for this column. A None value for row means all rows.

  Returns:
    A WHERE clause for the row template or the empty string if there is no none.
  *%._"z""z{field} LIKE "{pattern}")fieldpatternz{field} = {term})r   term z WHERE z AND )
r
   len
isinstancesixstring_typesreplaceappendr   r   join)row_templatetermsindexr   r   s        r   _Wherer&   3   s     %s<()% d		D#**	+,,sC(00c:BB3M/66E"G 7 5 	6 	'..E" / / 	0 * 

gll5)
))r   c                   J     e Zd ZdZ	 	 d fd	Zd Zd Zd Zd	dZd
dZ	 xZ
S )_TableaX  A persistent cache table.

  Attributes:
    name: The table name.
    deleted: Table was deleted if True.
    modified: Table modify timestamp.
    timeout: Tables older than timeout are invalid.
    _cache: The parent cache object.
    _fields: The f1,... fields name string.
    _values: The ?,... parameter replacement string for INSERT.
  c           	         d | _         t        t        |   |||||||       |r%| j                  j
                  j                  |       dj                  t        |      D cg c]  }t        |       c}      | _
        dj                  dg|z        | _        d| _        | j                  j                  r| | j                  j                  |<   y y c c}w )N)columnskeystimeoutmodified
restricted, ?F)_rowssuperr(   __init___cache_restrictedaddr"   r
   r   _fields_valuesdeleted	_metadata_tables)
selfcachenamer*   r+   r,   r-   r.   i	__class__s
            r   r3   z_Table.__init__^   s    DJ	&$ gD)08,6 ! 8 
kk!!$'99E'NCNqilNCDDL99cUW_-DLDL{{"&dkk$ 	 Ds   "Cc                 Z   | j                          | j                  j                  j                  dj	                  | j
                               | j                  j                  j                          | j                  j                  j                  | j
                  fg       d| _
        y)zDeletes the table.zDROP TABLE "{table}"tableTN)
Invalidater4   cursorexecuter   r>   _dbcommitr:   
DeleteRowsr9   r<   s    r   Deletez_Table.Deletem   sv    OOKK%%DII%68 	KKOOKK$$tyyl^4DLr   c                 .   | j                   rd| _         | j                  rZd| _        | j                  j                  j	                  | j
                  fg       | j                  j                  | j
                  = y| j                  j                  j                  t        j                  j                  | j
                  | j                  | j                  | j                  | j                  | j                  | j                  j                         g       yy)z#Commits changed/deleted table data.F)r>   r*   r+   r,   r-   r.   versionN)changedr9   r4   r:   rI   r>   r;   AddRowsr   MetadataRowr*   r+   r,   r-   r.   rM   rJ   s    r   _Commitz_Table._Commitw   s    ||dl	((499,8KK		*%%$$((YYYY??++ ) - .	/ r   c                    | j                  |       | j                  j                  j                  dj	                  | j
                  | j                  | j                        |       | j                  j                  j                          y)z#Adds each row in rows to the table.z=INSERT OR REPLACE INTO "{table}" ({fields}) VALUES ({values}))rC   fieldsvaluesN)

_CheckRowsr4   rE   executemanyr   r>   r7   r8   rG   rH   )r<   rowss     r   rO   z_Table.AddRows   se    OODKK""G))DLL 	 	G	
 	KKOOr   c           	         |rb| j                  |       |D ]K  }| j                  j                  j                  dj	                  | j
                  t        |                   M n?| j                  j                  j                  dj	                  | j
                               | j                  j                  j                          y)z@Deletes each row in the table matching any of the row_templates.zDELETE FROM "{table}"{where})rC   wherezDELETE FROM "{table}" WHERE 1rB   N)	_CheckRowTemplatesr4   rE   rF   r   r>   r&   rG   rH   )r<   row_templatestemplates      r   rI   z_Table.DeleteRows   s    
m,#(""*11iivh'7 2 9	: $
 kk  
)
0
0tyy
0
ACKKOOr   c           	         || j                  |g       |s[| j                  sO| j                  sCt        j                  dj                  | j                  j                  | j                              | j                  j                  j                  dj                  | j                  | j                  t        |                   | j                  j                  j                         S )z?Returns the list of rows that match row_template, None for all.z"[{}] cache table [{}] has expired.z%SELECT {fields} FROM "{table}"{where})rT   rC   rZ   )r[   r.   r-   r   CacheTableExpiredr   r4   r>   rE   rF   r7   r&   fetchall)r<   r#   ignore_expirations      r   Selectz_Table.Select   s    
|n-T__T]]((
.
5
5kk		+, , 	KK/66<<tyy|8L 	7 	NO ;;&&((r   )   rc   r   r   FN)NF)__name__
__module____qualname____doc__r3   rK   rR   rO   rI   rb   __classcell__r@   s   @r   r(   r(   Q   s0    
 JK'/()r   r(   c                   H     e Zd ZdZdZd	 fd	Zd Zd Zd Zd
dZ	d Z
 xZS )Cachea  A persistent cache object.

  Attributes:
    cursor: The _db operations cursor.
    name: The db path name. Created/removed by this object. May be a file or
      directory. In this implementation its a file.
    timeout: The default table timeout.
    version: A caller defined version string that must match the version string
      stored when the persistent object was created.
    _db: The db connection.
    _metadata: The metadata restricted _Table.
    _persistent: True if the persistent object has been committed at least once.
    _restricted: The set of restricted table names.
    _start: The cache instance start time.
    _tables: The map of open table objects.
  s   SQLite format 3c                    t         t        |   t        ||||       d| _        	 t        j                  |      5 }|j                  t        | j                              }|| j                  k7  r.t        j                  dj                  | j                              	 d d d        d| _        t#        j$                  |      | _        | j&                  j)                         | _        t+        dg      | _        i | _        d | _        t3        j4                         | _        	 | j9                          y # 1 sw Y   xY w# t
        j                  $ r3 |s.t        j                  dj                  | j                              Y t
        j                   $ r/ t        j                  dj                  | j                              w xY w# t        j                   $ r | j;                  d        w xY w)N)creater,   rM   Fz[{}] is not a persistent cache.Tz Persistent cache [{}] not found.__lock__rH   )r2   rl   r3   r(   _persistentr	   BinaryFileReaderreadr   _EXPECTED_MAGICr   CacheInvalidr   r>   MissingFileErrorCacheNotFoundErrorsqlite3connectrG   rE   setr5   r;   r:   r   Now_startInitializeMetadataClose)r<   r>   rn   r,   rM   factual_magicr@   s          r   r3   zCache.__init__   s   	%VWg   GD?!!$'1vvc$"6"6784///''/66tyyAC C 0 (
 d t$DH((//#DKJ<(DDLDN'++-DK
) (' !! B&&.55dii@B 	B  ;; ?##
+
2
2499
=? ??  
jjjs7   D< A"D0D< G 0D95D< <AGAG'G,c                     	 t        j                  | j                         y# t        $ r7}|j                  t        j
                  t        j                  fvr Y d}~yd}~ww xY w)z.Permanently deletes the persistent cache file.N)osremover>   OSErrorerrnoENOENTEISDIR)r<   es     r   _DeleteCacheFilezCache._DeleteCacheFile   sH    ii		 	
u||4	4 
5s   " 	A"-AA"c                 H    | j                  d       | j                          y)z4Closes and permanently deletes the persistent cache.Frp   N)r   r   rJ   s    r   rK   zCache.Delete   s    JJeJr   c                 D   | j                   j                         D cg c]  }|j                  s| c}D ]  }|j                           | j                  j                  r| j                  j                          | j
                  j                          d| _        yc c}w )z(Commits all operations up to this point.TN)r;   rU   rN   rR   r:   rG   rH   rq   )r<   xrC   s      r   CommitzCache.Commit   su     "\\002@2aii!2@mmo A~~
nnHHOOD As
   BBc                     | j                   rr|r| j                          | `| j                   j                          d| _         t	        j
                  d       d| _        |s| j                  s| j                          yyyy)z~Closes the cache, optionally committing any changes.

    Args:
      commit: Commits any changes before closing if True.
    N   )	rG   r   rE   closegccollectr;   rq   r   )r<   rH   s     r   r   zCache.Close   sh     xx	
+
hhnndhjjmdlD,, 	 -V r   c                    t        |      D cg c]  }t        |       }}t        |xs d      D cg c]  }t        |       }}|j                  dj                  dj	                  |                   dj                  dj	                  |            }| j
                  j                  dj                  ||             y	c c}w c c}w )
z-sqlite3 implementation specific _CreateTable.rc   zPRIMARY KEY ({keys})r/   )r+   z
({fields}))rT   z,CREATE TABLE IF NOT EXISTS "{name}" {fields})r>   rT   N)r
   r   r!   r   r"   rE   rF   )r<   r>   r*   r+   r?   
field_listkey_listrT   s           r   _ImplementationCreateTablez Cache._ImplementationCreateTable  s    (-g71)A,J7&+DIA&67&6	!&6H7,3389L3MN  		*(= >FKK6==f 	> 	&'	 87s
   CC
)TNN)T)re   rf   rg   rh   rt   r3   r   rK   r   r   r   ri   rj   s   @r   rl   rl      s.    " '/ D
 ('r   rl   rd   )rh   
__future__r   r   r   r   r   r   googlecloudsdk.core.cacher   r   r   googlecloudsdk.core.utilr	   r   	six.movesr
   ry   r   r&   Tabler(   CacheUsingMetadataTablerl    r   r   <module>r      sg    
 '  '  	 	 0 4 ; * 
  	+*<\)"(( \)~i'N22 i'r   