
    VhmR                        d dl mZmZmZ eZd dlmZmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d dlmZ d	Zd	Zd	Z ed
      Z	 d d	lZd dlmZ d dlmZ d dlmZ  eej:                        Ze ed      k  redZdej@                  j4                  iZe	efZ#e ed      k\  r' G d de      Z$ejJ                  jM                  de$       d Z'd Z(d)dZ)d*dZ*d+dZ+ G d d      Z, G d d e-      Z.d! Z/d" Z0d# Z1d$ Z2d% Z3d& Z4d' Z5d,d(Z6y	# e$ r6 	 d d	lZeZd dl!m"Z"  eej:                        ZdZde"iZn# e$ r dZY nw xY wY w xY w)-    )absolute_importdivisionprint_function)	timedeltadatetime)Decimal)environ)	to_native)missing_required_lib)	iteritems)LooseVersionNz0.0)ClientCursor)dict_row)TimestamptzLoaderz3.1Trow_factory)
DictCursorcursor_factoryF3c                        e Zd Z fdZ xZS )InfTimestamptzLoaderc                 v    |dk(  rt         j                  S |dk(  rt         j                  S t        |   |      S )Ns   infinitys	   -infinity)r   maxminsuperload)selfdata	__class__s     v/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/postgresql/plugins/module_utils/postgres.pyr   zInfTimestamptzLoader.load=   s6    {"||#%||#w|D))    )__name__
__module____qualname__r   __classcell__)r   s   @r   r   r   <   s    	* 	*r    r   timestamptzc                     t         } t        t        | j                  d      sdn| j                  d      dg      t        dd      t        ddg      t        dd	g      t        d
t        | j                  dd            dg      t        dg d      t        dg      t        d      t        d      t        i d      
      S )zx
    Return a dictionary with connection options.

    The options are commonly used by most of PostgreSQL modules.
    PGUSERpostgreslogin)defaultaliases T)r*   no_loghostunix_socketintPGPORTi8  
login_port)typer*   r+   prefer)allowdisabler4   requirez	verify-cazverify-full)r*   choicesssl_rootcert)r+   path)r3   dict)r*   r3   )

login_userlogin_password
login_hostlogin_unix_socketportssl_modeca_certssl_certssl_keyconnect_params)r	   r;   getr0   )env_varss    r   postgres_common_argument_specrH   H   s     H&.ll8&<J(,,xBXI
 Bt4VH5rM?CXt45!N

 

 n-.6"&!BV47 r    c                    t         s| j                  t        d             n#t        t	        d      k  r| j                  d       | j                  j                  d      r&t        t	        d      k  r| j                  d       yyy)	zCheck required libraries.psycopg2msgz2.5.1zEpsycopg should be at least 2.5.1 to support all modules functionalityrB   z2.4.3zEpsycopg2 must be at least 2.4.3 in order to use the ca_cert parameterN)HAS_PSYCOPG	fail_jsonr   PSYCOPG_VERSIONr   warnparamsrF   )modules    r   ensure_required_libsrS   p   so    1*=>	<0	0[\}}#,w:O(Ode )P#r    c                    d}d}	 t         t        d      k\  r-||d<   t        |d<   t        |d<   t	        j
                  di |}net        j
                  di |}|rNt         t        d      k\  r|j                  d       n)|j                  t        j                  j                         | j                  j                  d	      rt         t        d      k\  r+|j                  t        j                  j                  
      }n*|j                  t        j                  j                         }	 |j#                  d| j                  d	   z         |j+                          t         t        d      k\  rL|j                  t        j                  j                  
      }	 |j#                  d       |j+                          |1|r| j'                  d|z         ||fS | j1                  d|z         d}||fS # t$        $ r(}| j'                  dt)        |      z         Y d}~d}~ww xY w# |j+                          w xY w# t$        $ r(}| j'                  dt)        |      z         Y d}~d}~ww xY w# |j+                          w xY w# t,        $ r9}d|j.                  d   v r| j'                  d       t)        |      }Y d}~d}~wt$        $ r}t)        |      }Y d}~#d}~ww xY w)a  Connect to a PostgreSQL database.

    Return a tuple containing a psycopg connection object and error message / None.

    Args:
        module (AnsibleModule) -- object of ansible.module_utils.basic.AnsibleModule class
        conn_params (dict) -- dictionary with connection parameters

    Kwargs:
        autocommit (bool) -- commit automatically (default False)
        fail_on_conn (bool) -- fail if connection failed or just warn and return None (default True)
    Nz3.0
autocommitr   r   2.4.2T)rU   session_role)r   )r   zSET ROLE "%s"zCould not switch role: %srK   zSET datestyle TO isozCould not set date style: %ssslrootcertr   zEPostgresql server must be at least version 8.4 to support sslrootcertz!unable to connect to database: %sz$PostgreSQL server is unavailable: %s )rO   r   r   r   psycopgconnectrJ   set_sessionset_isolation_level
extensionsISOLATION_LEVEL_AUTOCOMMITrQ   rF   cursorrowsextrasr   execute	ExceptionrN   r
   close	TypeErrorargsrP   )rR   conn_paramsrU   fail_on_conndb_connectionconn_errr`   es           r   connect_to_dbrm   }   s    MH. l511(2K%,8K())1K&#OO:k:M$,,;{;M"l7&;;!--->!55h6I6I6d6de ==^,,u"55&--',,:O:O-P&--X__=W=W-X~1NNO  l511"))gll6K6K)LF56  !Dx!OP
 ("" KK>IJ M(""A  Q  %@9Q<%O PPQ   T  %CiPQl%R SST   AFF1I% "F G Q<  Q< s   D&J -!G3 AJ H< ,J 3	H$<HH' H$$H' 'H99J <	I-I(#I0 (I--I0 0JJ 	K$.KK$KK$c           	      Z   |r:| j                   j                  ||      }|r| j                  j                  |       y	 || j                   j	                  ||       n| j                   j	                  |       |rS|6| j                  j                  | j                   j                  ||             n| j                  j                  |       |s| j                   j                         }|S y# t        $ r5}| j                  j                  d|dt        |             Y d}~yd}~ww xY w)a  Execute SQL.

    Auxiliary function for PostgreSQL user classes.

    Returns a query result if possible or a boolean value.

    Args:
        obj (obj) -- must be an object of a user class.
            The object must have module (AnsibleModule class object) and
            cursor (psycopg cursor object) attributes
        query (str) -- SQL query to execute

    Kwargs:
        query_params (dict or tuple) -- Query parameters to prevent SQL injections,
            could be a dict or tuple
        return_bool (bool) -- return True instead of rows if a query was successfully executed.
            It's necessary for statements that don't return any result like DDL queries (default False).
        add_to_executed (bool) -- append the query to obj.executed_queries attribute
        dont_exec (bool) -- used with add_to_executed=True to generate a query, add it
            to obj.executed_queries list and return True (default False)
    TNzCannot execute SQL 'z': rK   F)
r`   mogrifyexecuted_queriesappendrc   fetchallrd   rR   rN   r
   )objqueryquery_paramsreturn_booladd_to_executed	dont_execresrl   s           r   exec_sqlrz      s   .  

""5,7  ''.X#JJul3JJu%'$$++CJJ,>,>ul,ST$$++E2**%%'CJ X

%ST!VWWXs   B,C, ,	D*5+D%%D*c           	      j   ddddddddd	t         t        d
      k\  rY|j                  d      rdd<   n|j                  d      rdd<   n|j                  d      rdd<   nl|rj| j                  d       nX|j                  d      rdd<   nA|j                  d      rdd<   n*|j                  d      rdd<   n|r| j                  d       t	        fdt        |      D              }d}d|vs|d   dv rd}|r|d   dk7  r|d   |d<   |j                  d      r|j                  |d          |S )a  Get connection parameters from the passed dictionary.

    Return a dictionary with parameters to connect to PostgreSQL server.

    Args:
        module (AnsibleModule) -- object of ansible.module_utils.basic.AnsibleModule class
        params_dict (dict) -- dictionary with variables

    Kwargs:
        warn_db_default (bool) -- warn that the default DB is used (default True)
    r.   userpasswordr@   sslmoderX   sslcertsslkey)r>   r<   r=   r@   rA   rB   rC   rD   z2.7.0dbdbnamedatabaselogin_dbzGDatabase name has not been passed, used default database to connect to.c              3   H   K   | ]  \  }}|v r|d k7  r|	|   |f  yw)r,   NrY   ).0kv
params_maps      r   	<genexpr>z"get_conn_params.<locals>.<genexpr>.  s8      @VajQ"W !}a  @s   "F)N	localhostTr?   r,   rE   )rO   r   rF   rP   r;   r   update)rR   params_dictwarn_db_defaultkwis_localhostr   s        @r   get_conn_paramsr      sj     $ 	J ,w//??4 'Jt__Z(%-Jz"__Z(%-Jz" C D ??4 )Jt__Z(%/Jz"__Z(%/Jz" C D 
 @y/E @ 
@B LR2f:)<<$78B> !456
 '(
		+./0Ir    c                       e Zd Zd Zd Zy)PgRolec                 X    || _         || _        || _        | j                         | _        y )N)rR   r`   name_PgRole__fetch_membersmemberof)r   rR   r`   r   s       r   __init__zPgRole.__init__A  s'    	,,.r    c                 T    d}t        | |d| j                  id      }|r|d   d   S g S )NzSELECT ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) FROM pg_catalog.pg_roles r WHERE r.rolname = %(dst_role)sdst_roleF)ru   rw   r   array)rz   r   )r   rt   ry   s      r   __fetch_memberszPgRole.__fetch_membersG  s=    2 tU*dii1H',.q6'?"Ir    N)r!   r"   r#   r   r   rY   r    r   r   r   @  s    /r    r   c                   2    e Zd ZddZd Zd Zd Zd Zd Zy)	PgMembershipc                 4   || _         || _        |D cg c]  }|j                          c}| _        |D cg c]  }|j                          c}| _        g | _        i | _        i | _        || _        g | _	        d| _
        | j                          y c c}w c c}w )NF)rR   r`   striptarget_rolesgroupsrp   grantedrevokedfail_on_rolenon_existent_roleschanged _PgMembership__check_roles_exist)r   rR   r`   r   r   r   rs          r   r   zPgMembership.__init__X  s    0<=1QWWY=*01Qqwwy1 "("$  " >1s
   BBc                 j   | j                   D ]  }g | j                  |<   | j                  D ]y  }t        | j                  | j
                  |      }||j                  v r3d|d|d}t        | |d      | _        | j                  s\| j                  |   j                  |       {  | j                  S )NGRANT "" TO ""Trv   )
r   r   r   r   rR   r`   r   rz   r   rq   r   grouprolerole_objrt   s        r   grantzPgMembership.grante  s    [[ 	5E"$DLL)) 
5!$++t{{DAH--- . 16t<'eF<<LL'..t4
5	5 ||r    c                 j   | j                   D ]  }g | j                  |<   | j                  D ]y  }t        | j                  | j
                  |      }||j                  vr3d|d|d}t        | |d      | _        | j                  s\| j                  |   j                  |       {  | j                  S )NREVOKE "" FROM "r   Tr   )
r   r   r   r   rR   r`   r   rz   r   rq   r   s        r   revokezPgMembership.revokew  s    [[ 	5E"$DLL)) 
5!$++t{{DA 1 11 2 49$?'eF<<LL'..t4
5	5 ||r    c                 j   | j                   D ]  }t        | j                  | j                  |      }t	        | j
                        }t	        |j                        }||z
  }|D ][  }d|d|d}t        | |d      | _        || j                  v r| j                  |   j                  |       L|g| j                  |<   ] ||z
  }|D ][  }d|d|d}t        | |d      | _        || j                  v r| j                  |   j                  |       L|g| j                  |<   ]  | j                  S )Nr   r   r   Tr   r   r   )r   r   rR   r`   setr   r   rz   r   r   rq   r   )	r   r   r   desired_groupscurrent_groupsgroups_to_revoker   rt   groups_to_grants	            r   matchzPgMembership.match  s&   %% 	1Ddkk4;;=H -N !2!23N->) 138$?'eFDLL(LL'..t4+/&DLL'1 -~=O( 105t<'eFDLL(LL'..t4+/&DLL'1%	14 ||r    c                    | j                   r| j                  | j                         }| j                   D ]l  }||vs| j                  r | j                  j	                  d|z         4| j                  j                  d|z         | j                  j                  |       n | j                  | j                        }| j                  D ]  }||vs| j                  r | j                  j	                  d|z         n| j                  j                  d|z         || j                   vr| j                  j                  |       || j                  r$| j                  j                  d|d|d       | j                  j                  d|d|d        | j                   r.| j                   D cg c]  }|| j                  vs| c}| _         | j                  D cg c]  }|| j                  vs| c}| _        y c c}w c c}w )NzRole %s does not existrK   zRole %s does not exist, passzRole role 'z' is a member of role ''z', pass)
r   _PgMembership__roles_existr   rR   rN   rP   r   rq   r   	exit_json)r   existent_groupsr   existent_rolesr   gr   s          r   __check_roles_existz PgMembership.__check_roles_exist  s   ;;"00=O >/((--2JU2R-S(()G%)OP//66u=> ++D,=,=>%% 	iD>)$$KK)).F.M)NKK$$%Cd%JKt{{*++2248 ((--_cei2j-k((\`bf)gh	i" ;;&*kkVQd>U>U5U1VDK(,(9(9^1QdF]F]=]Q^ W^s   4HH"H6Hc                     |D cg c]
  }d|z   dz    }}ddj                  |      z  }t        | |d      D cg c]  }|d   	 c}S c c}w c c}w )Nr   z2SELECT rolname FROM pg_roles WHERE rolname IN (%s),F)rw   rolname)joinrz   )r   rolesxtmprt   s        r   __roles_existzPgMembership.__roles_exist  sV    &+,sQw},,DsxxPS}T&.tUE&RS)SS -Ss
   A	ANT)	r!   r"   r#   r   r   r   r   r   r   rY   r    r   r   r   W  s#    #$$:!_FTr    r   c                 ,    | j                  d|z         y)zSet session's search_path.

    Args:
        cursor (Psycopg cursor): Database cursor object.
        search_path (str): String containing comma-separated schema names.
    zSET search_path TO %sN)rc   )r`   search_paths     r   set_search_pathr     s     NN*[89r    c                    t        | t              r4t        |       D ]$  \  }}t        |t              st	        |      | |<   & | S t        | t              r2t        |       D ]$  \  }}t        |t              st	        |      | |<   & | S )zConvert list elements of the passed object
    to PostgreSQL arrays represented as strings.

    Args:
        obj (dict or list): Object whose elements need to be converted.

    Returns:
        obj (dict or list): Object with converted elements.
    )
isinstancer;   r   listlist_to_pg_array	enumerate)rs   keyelemis       r   convert_elements_to_pg_arraysr     s     #t$S> 	2KS$$%+D1C	2 J 
C	 ~ 	0GAt$%)$/A	0 Jr    c                 J    t        |       j                  d      } d| z   dz   } | S )zConvert the passed list to PostgreSQL array
    represented as a string.

    Args:
        elem (list): List that needs to be converted.

    Returns:
        elem (str): String representation of PostgreSQL array.
    z[]{})strr   )r   s    r   r   r     s)     t9??4 D:DKr    c                 r    t        | t              rt        |       S t        | t              rt	        |       S | S )zConvert unsupported type to appropriate.
    Args:
        val (any) -- Any value fetched from database.
    Returns value of appropriate type.
    )r   r   floatr   r   )vals    r   convert_to_supportedr     s0     #wSz	C	#3xJr    c                 j    t         t        d      k\  r| j                  j                  S | j                  S )zGet server version.

    Args:
        conn (psycopg.Connection) -- Psycopg connection object.

    Returns server version (int).
    z3.0.0)rO   r   infoserver_version)conns    r   get_server_versionr     s-     ,w//yy'''"""r    c                     t         t        d      k\  r|| _        y|r*| j                  t        j
                  j                         y| j                  t        j
                  j                         y)z{Set autocommit.

    Args:
        conn (psycopg.Connection) -- Psycopg connection object.
        autocommit -- bool.
    rV   N)rO   r   rU   r]   rJ   r^   r_   ISOLATION_LEVEL_READ_COMMITTED)r   rU   s     r   set_autocommitr     sO     ,w//$$$X%8%8%S%ST$$X%8%8%W%WXr    c                 r    d}|dk(  rd}n|dk(  rd}| j                  |d|i       | j                         d   S )a   Get DB object's comment.

    Args:
        cursor (Psycopg cursor) -- Database cursor object.
        obj_name (str) -- DB object name to get comment from.
        obj_type (str) -- Object type.

    Returns object's comment (str) if present or None.
    r,   r   zSELECT pg_catalog.shobj_description(r.oid, 'pg_authid') AS comment FROM pg_catalog.pg_roles AS r WHERE r.rolname = %(obj_name)s	extensionzSELECT pg_catalog.obj_description(e.oid, 'pg_extension') AS comment FROM pg_catalog.pg_extension AS e WHERE e.extname = %(obj_name)sobj_namecomment)rc   fetchone)r`   obj_typer   rt   s       r   get_commentr   ,  sP     E62 
[	 2 NN5:x01??Y''r    c                     d|j                         d|d}|s| j                  |dz   d|i       |&|j                  | j                  |dz   d|i             y)aK  Get DB object's comment.

    Args:
        cursor (Psycopg cursor) -- Database cursor object.
        comment(str) -- Comment to set on object.
        obj_name (str) -- DB object name to set comment on.
        obj_type (str) -- Object type.
        executed_statements (list) -- List of executed state-modifying statements.
    zCOMMENT ON z "z" IS z%(comment)sr   T)upperrc   rq   ro   )r`   r   r   r   
check_moderp   rt   s          r   set_commentr   D  s]     )1(8(CEu},y'.BC#u}/DyRYFZ [\r    )FT)NFTFr   )TN)7
__future__r   r   r   r3   __metaclass__r   r   decimalr   osr	   ansible.module_utils._textr
   ansible.module_utils.basicr   ansible.module_utils.sixr   Eansible_collections.community.postgresql.plugins.module_utils.versionr   rZ   rJ   pg_cursor_argsrO   r   psycopg.rowsr   psycopg.types.datetimer   __version__ImportErrorrM   ra   psycopg2.extrasr   TYPES_NEED_TO_CONVERTr   adaptersregister_loaderrH   rS   rm   rz   r   r   objectr   r   r   r   r   r   r   r   r   rY   r    r   <module>r	     s   A @ (   0 ; . u%$%8 #7#6#67Oe,,K#W\\%:%:;N !),  l3''*0 * $$]4HI%P
fG#T2jAH .uT6 uTp:.#Y (0o  	.&x';';<*J7 	s7   AD E	$D98E	9E E	EE	E	