§
    öÛgp  ã                   ó–   — d Z ddlZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z ej        d	¦  «        Z	d
„ Z
d„ Zdd„Zdd„Zdd„Zd„ Zd„ Zdd„Zdd„ZdS )a  
String split and join operations for dealing with literals and identifiers.

Notably, the functions in this module are intended to be used for simple
use-cases. It attempts to stay away from "real" parsing and simply provides
functions for common needs, like the ability to identify unquoted portions of a
query string so that logic or transformations can be applied to only unquoted
portions. Scanning for statement terminators, or safely interpolating
identifiers.

All functions deal with strict quoting rules.
é    Nc                 ó.   — |                       dd¦  «        S )z#Replace every instance of ' with ''ú'ú''©Úreplace©Útexts    úG/granary/edev/quantum/lib/python3.11/site-packages/postgresql/string.pyÚescape_literalr      ó   € à�Š�S˜$ÑÔÐó    c                 ó:   — d|                       dd¦  «        z   dz   S )z5Escape the literal and wrap it in [single] quotationsr   r   r   r   s    r
   Úquote_literalr      ó    € àˆd�lŠl˜3 Ñ%Ô%Ñ%¨Ñ+Ð+r   c                 ó.   — |                       dd¦  «        S )z#Replace every instance of " with ""ú"ú""r   r   s    r
   Úescape_identr      r   r   c                 óŽ   — | oB| d                               ¦   «          o'|                      dd¦  «                             ¦   «          S )Nr   Ú_Úa)Ú	isdecimalr   Úisalnumr   s    r
   Úneeds_quotingr      sB   € ØÐR˜$˜qœ'×+Ò+Ñ-Ô-Ð-ÐR°$·,²,¸sÀCÑ2HÔ2H×2PÒ2PÑ2RÔ2RÐSÐSr   c                 ó:   — d|                       dd¦  «        z   dz   S )z;Replace every instance of ' with  *and* place ' on each endr   r   r   r   s    r
   Úquote_identr   !   r   r   c                 óB   — t          | ¦  «        rt          | ¦  «        n| S )zu
	If needed, replace every instance of '"' with '""' *and* place '"' on each end.
	Otherwise, just return the text.
	)r   r   r   s    r
   Úquote_ident_if_neededr   %   s$   € õ
 +¨4Ñ0Ô0Ð:��DÑÔÐ°dÐ:r   a  (?xu)
	E'(?:''|\\.|[^'])*(?:'|$)          (?# Backslash escapes E'str')
|	'(?:''|[^'])*(?:'|$)               (?# Regular literals 'str')
|	"(?:""|[^"])*(?:"|$)               (?# Identifiers "str")
|	(\$(?:[^0-9$]\w*)?\$).*?(?:\1|$)   (?# Dollar quotes $$str$$)
c              #   ó|  K  — d}t           } |j        | ¦  «        }|                     ¦   «         }|��}| ||                     ¦   «         …         V — |                     ¦   «         d         }|�t          |¦  «        }|}|}n+d}| |                     ¦   «                  }	|	dk    rd}d}n|	x}}| |                     ¦   «         |z
  |                     ¦   «         …         |k    s-|                     ¦   «         |z
  |                     ¦   «         k    r2|| |                     ¦   «         t          |¦  «        z   d…         fV — dS || |                     ¦   «         t          |¦  «        z   |                     ¦   «         |z
  …         fV — |                     ¦   «         }|                     ¦   «         }|�­}| |d…         V — dS )aŸ  
	split the string up by into non-quoted and quoted portions. Zero and even
	numbered indexes are unquoted portions, while odd indexes are quoted
	portions. 

	Unquoted portions are regular strings, whereas quoted portions are
	pair-tuples specifying the quotation mechanism and the content thereof.

	>>> list(split("select $$foobar$$"))
	['select ', ('$$', 'foobar'), '']

	If the split ends on a quoted section, it means the string's quote was not
	terminated. Subsequently, there will be an even number of objects in the
	list.

	Quotation errors are detected, but never raised. Rather it's up to the user
	to identify the best course of action for the given split.
	r   Né   ÚEúE'r   )Úquote_reÚscannerÚsearchÚstartÚgroupsÚlenÚend)
r	   ÚlastendÚreÚscanÚmatchÚdqÚendoffÚquoter)   Úqs
             r
   Úsplitr2   3   s±  è è € ð& €Ý€ØˆŒ
�4ÑÔ€Ø	�Š‰Œ€ØÑàˆW�U—[’[‘]”]Ð"Ô#Ð#Ð#Ð#à‡|‚|�~„~�aÔ€"Ø€^Ý�‰GŒG€6Ø€5Ø	€3€3à€6ØˆE�KŠK‰MŒMÔ€1Øˆ3‚h€hØ€EØ
€C€Cà€O€Cˆ%ð
 
ˆ%�)Š)‰+Œ+�fÑ
˜UŸYšY™[œ[Ð
(Ô)¨SÒ0Ð0Ø
‡Y‚Y�[„[�6Ñ˜UŸ[š[™]œ]Ò*Ð*Ø
��e—k’k‘m”m¥C¨¡J¤JÑ.Ð/Ð/Ô0Ð	1Ð1Ð1Ð1Ø€5à
��e—k’k‘m”m¥C¨¡J¤JÑ.¨u¯yªy©{¬{¸6Ñ/AÐAÔBÐ	CÐCÐCÐCà�IŠI‰KŒK€'Ø
�+Š+‰-Œ-€%ð; Ñð@ 	ˆWˆXˆXŒÐÐÐÐÐr   c                 ó¸   — d}d}t          | ¦  «        }d}|D ]A}|||z   z  }	 t          |¦  «        \  }}|||z   z  }|dk    rd}n|}Œ1# t          $ r Y  nw xY w|S )z‡
	catenate a split string. This is needed to handle the special
	cases created by pg.string.split(). (Run-away quotations, primarily)
	Ú Fr"   r   )ÚiterÚnextÚStopIteration)Úsplitted_iterÚsÚquotedÚiÚendqÚxr1   Úqtexts           r
   Úunsplitr?   l   sš   € ð
 €Ø
€Ý	ˆ-ÑÔ€Ø
€Ø
ð 
	ð 
	€QØ€tˆa�x�-€!ð	Ý�1‰gŒg�8€1€eØˆˆE‰	�>€1Øˆ4‚i€iØ€D€Dà€DøøÝ	ð 	ð 	ð 	Ø€5€5ð	øøøà	€s   £%A	Á	
AÁAú.éÿÿÿÿc                 ó  — |dz  }t          |¦  «        }d}t          | ¦  «        }|}|| vr|                      ||¦  «        S g }	t          |	¦  «        |k    �r|                      ||¦  «        }
|
dk    rnú|                      |||
¦  «        }|dk    r |                      ||dz   ¦  «        }|dk    r>|                      ||||z   ¦  «        |k    rn"|                      ||dz   ¦  «        }|dk    °>d}
n@|                      ||dz   ¦  «        }
|
dk    rn |                      ||dz   |
¦  «        }|dk    ° |
dk    rn6|	                     | ||
…         ¦  «         |
dz   }t          |	¦  «        |k    �°|	                     | |d…         ¦  «         |	S )z·
	split the string on the seperator ignoring the separator in quoted areas.

	This is only useful for simple quoted strings. Dollar quotes, and backslash
	escapes are not supported.
	é   r   rA   r    N)r(   r2   ÚfindÚappend)r	   r0   ÚsepÚmaxsplitÚescapeÚesclenÚoffsetÚtlr)   ÚlÚnextsepÚ	nextquotes               r
   Úsplit_usingrO   ‚   sÃ  € ð �!‰)€Ý
ˆf‰+Œ+€Ø
€Ý	ˆ$�i„i€Ø	€à	�ÐÐØ	�Š�C˜Ñ	"Ô	"Ð"Ø€å
ˆ1�v„v�ÒÑà�IŠI�c˜6Ñ"Ô"€'Ø�‚]€]àð �yŠy˜ ¨Ñ0Ô0€9Ø	�bŠˆð —	’	˜% ¨Q¡Ñ0Ô0€IØ
�rŠ/ˆ/Ø�	Š	�&˜) Y¨vÑ%5Ñ6Ô6¸)ÒCÐCàà—’˜5 )¨a¡-Ñ0Ô0€Yð �rŠ/ˆ/ð €WØ
à�iŠi˜˜Y¨™]Ñ+Ô+€GØ�"‚}€}ð Ø—	’	˜% ¨Q¡°Ñ8Ô8€Ið+ 
�bŠˆð, �‚m€mØ	à‡8‚8ˆD�˜�Ô Ñ!Ô!Ð!Ø�a‰K€6õG ˆ1�v„v�ÒÑðH ‡‚ˆ$ˆvˆwˆwŒ-ÑÔÐØ	€r   ú,r   c                 óÂ  — g }t          | |||¬¦  «        D ]È}|                     ¦   «         }|                     d¦  «        rW|                     d¦  «        st	          d|¦  «        ‚|                     |dd…                              dd¦  «        ¦  «         Œ‚t          |¦  «        rt	          d|¦  «        ‚|                     |                     ¦   «         ¦  «         ŒÉ|S )z@
	Split a series of identifiers using the specified separator.
	)rF   rG   r   z!unterminated identifier quotationr    rA   r   z+non-ident characters in unquoted identifier)	rO   ÚstripÚ
startswithÚendswithÚ
ValueErrorrE   r   r   Úlower)r	   rF   r0   rG   Únrr=   s         r
   Úsplit_identrX   º   së   € ð 	€Ý
�d˜E¨¸Ð
BÑ
BÔ
Bð ð €QØ‡g‚g�i„i€!Ø‡\‚\�#ÑÔð Ø
�*Š*�S‰/Œ/ð *Ý
Ø(¨!ñô ð ð ‡I‚Iˆa��"�Œg�oŠo˜d CÑ(Ô(Ñ)Ô)Ð)Ð)Ý�QÑÔð Ý	Ø1°1ñ
ô 
ð ð ‡9‚9ˆQ�WŠW‰YŒYÑÔÐÐØ
€r   c                 ó&   — t          | |d¬¦  «        S )z4
	Call to .split_ident() with a '.' sep parameter.
	r@   )rG   rF   )rX   )r	   rG   s     r
   Úsplit_qnamerZ   Ò   s   € õ 	�D X°SÐ9Ñ9Ô9Ð9r   c                  ó@   — d                      d„ | D ¦   «         ¦  «        S )z-Quote the identifiers and join them using '.'r@   c                 ó,   — g | ]}t          |¦  «        ‘ŒS © )r   ©Ú.0r=   s     r
   ú
<listcomp>zqname.<locals>.<listcomp>Ú   s   € Ð/Ð/Ð/ Q•+˜a‘.”.Ð/Ð/Ð/r   ©Újoin©Úargss    r
   Úqnamere   Ø   s#   € à�ŠÐ/Ð/¨$Ð/Ñ/Ô/Ñ0Ô0Ð0r   c                  ó@   — d                      d„ | D ¦   «         ¦  «        S )Nr@   c                 ó,   — g | ]}t          |¦  «        ‘ŒS r]   )r   r^   s     r
   r`   z#qname_if_needed.<locals>.<listcomp>Ý   s!   € Ð9Ð9Ð9¨qÕ'¨Ñ*Ô*Ð9Ð9Ð9r   ra   rc   s    r
   Úqname_if_neededrh   Ü   s#   € Ø�ŠÐ9Ð9°DÐ9Ñ9Ô9Ñ:Ô:Ð:r   ú;c              #   ó¸  K  — t          t          | ¦  «        ¦  «        }g }|D ]®}|                     |¦  «        }t          |¦  «        dk     r|                     |¦  «         n:|                     |d         ¦  «         |V — |dd…         D ]}|fV — Œ|d         g}	 |                     t	          |¦  «        ¦  «         Œž# t
          $ r Y  nw xY w|r|V — dS dS )aF  
	Given SQL, safely split using the given separator.
	Notably, this yields fully split text. This should be used instead of
	split_sql_str() when quoted sections need be still be isolated.

	>>> list(split_sql('select $$1$$ AS "foo;"; select 2;'))
	[['select ', ('$$', '1'), ' AS ', ('"', 'foo;'), ''], (' select 2',), ['']]
	rC   r   r    rA   N)r5   r2   r(   rE   r6   r7   )ÚsqlrF   r;   ÚcurÚpartÚsectionsr=   s          r
   Ú	split_sqlro   ß   s  è è € õ 
�%�‰*Œ*ÑÔ€Ø	€Øð 	ð 	€TØ�ZŠZ˜‰_Œ_€(åˆ�]„]�QÒÐØ‡:‚:ˆdÑÔÐÐà‡:‚:ˆh�qŒkÑÔÐØ	€9€9€9Ø�Q�r�TŒNð ð €qØˆ$€J€J€J€JØ
�2Œ,ˆ€3ð	Ø‡:‚:�d�1‰gŒgÑÔÐÐøÝ	ð 	ð 	ð 	Ø€5€5ð	øøøàð Ø€)€)€)€)€)ðð s   Â"CÃ
CÃCc              #   óT   K  — t          | |¬¦  «        D ]}t          |¦  «        V — ŒdS )zŸ
	Identical to split_sql but yields unsplit text.

	>>> list(split_sql_str('select $$1$$ AS "foo;"; select 2;'))
	['select $$1$$ AS "foo;"', ' select 2', '']
	)rF   N)ro   r?   )rk   rF   r=   s      r
   Úsplit_sql_strrq   ü   sC   è è € õ �C˜sÐ
#Ñ
#Ô
#ð ð €QÝ�‰
Œ
ÐÐÐÐðð r   )r@   rA   )rP   r   rA   )rA   )ri   )Ú__doc__r+   r   r   r   r   r   r   Úcompiler#   r2   r?   rO   rX   rZ   re   rh   ro   rq   r]   r   r
   ú<module>rt      s=  ððð ð 
€	€	€	ð ð  ð  ð,ð ,ð ,ð ð  ð  ðTð Tð Tð,ð ,ð ,ð;ð ;ð ;ð ˆ2Œ:ð ñ ô €ð7ð 7ð 7ðr
ð 
ð 
ð,6
ð 6
ð 6
ð 6
ðpð ð ð ð0:ð :ð :ð :ð1ð 1ð 1ð;ð ;ð ;ðð ð ð ð:ð ð ð ð ð r   