B *]:@sdZddlZddlmZddlmZmZeZ Gddde Z Gddde Z Gd d d e Z Gd d d e ZGd dde ZGddde Ze dZe dZdS)zSQL composition utility module N) extensions)PY3 string_typesc@sHeZdZdZddZddZddZdd Zd d Zd d Z ddZ dS) Composablea6 Abstract base class for objects that can be used to compose an SQL string. `!Composable` objects can be passed directly to `~cursor.execute()`, `~cursor.executemany()`, `~cursor.copy_expert()` in place of the query string. `!Composable` objects can be joined using the ``+`` operator: the result will be a `Composed` instance containing the objects joined. The operator ``*`` is also supported with an integer argument: the result is a `!Composed` instance containing the left argument repeated as many times as requested. cCs ||_dS)N)_wrapped)selfwrappedr ?/opt/alt/python37/lib64/python3.7/site-packages/psycopg2/sql.py__init__1szComposable.__init__cCsd|jj|jfS)Nz%s(%r)) __class____name__r)rr r r __repr__4szComposable.__repr__cCstdS)aj Return the string value of the object. :param context: the context to evaluate the string into. :type context: `connection` or `cursor` The method is automatically invoked by `~cursor.execute()`, `~cursor.executemany()`, `~cursor.copy_expert()` if a `!Composable` is passed instead of the query string. N)NotImplementedError)rcontextr r r as_string7s zComposable.as_stringcCs>t|trt|g|St|tr6t|gt|gStSdS)N) isinstanceComposedrNotImplemented)rotherr r r __add__Ds   zComposable.__add__cCst|g|S)N)r)rnr r r __mul__LszComposable.__mul__cCst|t|ko|j|jkS)N)typer)rrr r r __eq__OszComposable.__eq__cCs || S)N)r)rrr r r __ne__RszComposable.__ne__N) r __module__ __qualname____doc__r rrrrrrr r r r r#s  rcsLeZdZdZfddZeddZddZdd Zd d Z d d Z Z S)ra A `Composable` object made of a sequence of `!Composable`. The object is usually created using `!Composable` operators and methods. However it is possible to create a `!Composed` directly specifying a sequence of `!Composable` as arguments. Example:: >>> comp = sql.Composed( ... [sql.SQL("insert into "), sql.Identifier("table")]) >>> print(comp.as_string(conn)) insert into "table" `!Composed` objects are iterable (so they can be used in `SQL.join` for instance). csFg}x,|D]$}t|ts$td|||q Wtt||dS)Nz4Composed elements must be Composable, got %r instead)rr TypeErrorappendsuperrr )rseqri)r r r r hs   zComposed.__init__cCs t|jS)z+The list of the content of the `!Composed`.)listr)rr r r r"rsz Composed.seqcCs.g}x|jD]}|||q Wd|S)N)rr rjoin)rrrvr#r r r rws zComposed.as_stringcCs t|jS)N)iterr)rr r r __iter__}szComposed.__iter__cCs<t|trt|j|jSt|tr4t|j|gStSdS)N)rrrrr)rrr r r rs   zComposed.__add__cCs0t|trt|}nt|ts&td||S)a| Return a new `!Composed` interposing the *joiner* with the `!Composed` items. The *joiner* must be a `SQL` or a string which will be interpreted as an `SQL`. Example:: >>> fields = sql.Identifier('foo') + sql.Identifier('bar') # a Composed >>> print(fields.join(', ').as_string(conn)) "foo", "bar" z3Composed.join() argument must be a string or an SQL)rrSQLrr&)rZjoinerr r r r&s    z Composed.join) r rrrr propertyr"rr)rr& __classcell__r r )r r rVs rcsDeZdZdZfddZeddZddZdd Zd d Z Z S) r*aA A `Composable` representing a snippet of SQL statement. `!SQL` exposes `join()` and `format()` methods useful to create a template where to merge variable parts of a query (for instance field or table names). The *string* doesn't undergo any form of escaping, so it is not suitable to represent variable identifiers or values: you should only use it to pass constant strings representing templates or snippets of SQL statements; use other objects such as `Identifier` or `Literal` to represent variable parts. Example:: >>> query = sql.SQL("select {0} from {1}").format( ... sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]), ... sql.Identifier('table')) >>> print(query.as_string(conn)) select "foo", "bar" from "table" cs&t|tstdtt||dS)NzSQL values must be strings)rrrr!r*r )rstring)r r r r s z SQL.__init__cCs|jS)z(The string wrapped by the `!SQL` object.)r)rr r r r-sz SQL.stringcCs|jS)N)r)rrr r r rsz SQL.as_stringc Osg}d}xt|jD]\}}}}|r.td|r:td|rL|t||dkrVq|r|rjtd||t|d}q|s|dkrtd||||d7}q|||qWt|S)a^ Merge `Composable` objects into a template. :param `Composable` args: parameters to replace to numbered (``{0}``, ``{1}``) or auto-numbered (``{}``) placeholders :param `Composable` kwargs: parameters to replace to named (``{name}``) placeholders :return: the union of the `!SQL` string with placeholders replaced :rtype: `Composed` The method is similar to the Python `str.format()` method: the string template supports auto-numbered (``{}``), numbered (``{0}``, ``{1}``...), and named placeholders (``{name}``), with positional arguments replacing the numbered placeholders and keywords replacing the named ones. However placeholder modifiers (``{0!r}``, ``{0:<10}``) are not supported. Only `!Composable` objects can be passed to the template. Example:: >>> print(sql.SQL("select * from {} where {} = %s") ... .format(sql.Identifier('people'), sql.Identifier('id')) ... .as_string(conn)) select * from "people" where "id" = %s >>> print(sql.SQL("select * from {tbl} where {pkey} = %s") ... .format(tbl=sql.Identifier('people'), pkey=sql.Identifier('id')) ... .as_string(conn)) select * from "people" where "id" = %s rz(no format specification supported by SQLz%no format conversion supported by SQLNz6cannot switch from automatic field numbering to manualz6cannot switch from manual field numbering to automatic) _formatterparser ValueErrorr r*isdigitintr) rargskwargsr'ZautonumZprenamespecZconvr r r formats2  z SQL.formatcCs^g}t|}y|t|Wntk r2Yn$Xx |D]}||||q:Wt|S)a Join a sequence of `Composable`. :param seq: the elements to join. :type seq: iterable of `!Composable` Use the `!SQL` object's *string* to separate the elements in *seq*. Note that `Composed` objects are iterable too, so they can be used as argument for this method. Example:: >>> snip = sql.SQL(', ').join( ... sql.Identifier(n) for n in ['foo', 'bar', 'baz']) >>> print(snip.as_string(conn)) "foo", "bar", "baz" )r(r next StopIterationr)rr"r'itr#r r r r&s  zSQL.join) r rrrr r+r-rr8r&r,r r )r r r*s   @r*csHeZdZdZfddZeddZeddZdd Zd d Z Z S) Identifiera* A `Composable` representing an SQL identifier or a dot-separated sequence. Identifiers usually represent names of database objects, such as tables or fields. PostgreSQL identifiers follow `different rules`__ than SQL string literals for escaping (e.g. they use double quotes instead of single). .. __: https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html# SQL-SYNTAX-IDENTIFIERS Example:: >>> t1 = sql.Identifier("foo") >>> t2 = sql.Identifier("ba'r") >>> t3 = sql.Identifier('ba"z') >>> print(sql.SQL(', ').join([t1, t2, t3]).as_string(conn)) "foo", "ba'r", "ba""z" Multiple strings can be passed to the object to represent a qualified name, i.e. a dot-separated sequence of identifiers. Example:: >>> query = sql.SQL("select {} from {}").format( ... sql.Identifier("table", "field"), ... sql.Identifier("schema", "table")) >>> print(query.as_string(conn)) select "table"."field" from "schema"."table" cs@|s tdx|D]}t|tstdqWtt||dS)NzIdentifier cannot be emptyz$SQL identifier parts must be strings)rrrr!r<r )rstringss)r r r r As    zIdentifier.__init__cCs|jS)z5A tuple with the strings wrapped by the `Identifier`.)r)rr r r r=KszIdentifier.stringscCs$t|jdkr|jdStddS)z0The string wrapped by the `Identifier`. r.rz2the Identifier wraps more than one than one stringN)lenrAttributeError)rr r r r-Ps zIdentifier.stringcCsd|jjdtt|jfS)Nz%s(%s)z, )r r r&mapreprr)rr r r rZszIdentifier.__repr__csdfdd|jDS)N.c3s|]}t|VqdS)N)extZ quote_ident).0r>)rr r `sz'Identifier.as_string..)r&r)rrr )rr r_szIdentifier.as_string) r rrrr r+r=r-rrr,r r )r r r<"s   r<c@s$eZdZdZeddZddZdS)Literala A `Composable` representing an SQL value to include in a query. Usually you will want to include placeholders in the query and pass values as `~cursor.execute()` arguments. If however you really really need to include a literal value in the query you can use this object. The string returned by `!as_string()` follows the normal :ref:`adaptation rules ` for Python objects. Example:: >>> s1 = sql.Literal("foo") >>> s2 = sql.Literal("ba'r") >>> s3 = sql.Literal(42) >>> print(sql.SQL(', ').join([s1, s2, s3]).as_string(conn)) 'foo', 'ba''r', 42 cCs|jS)z%The object wrapped by the `!Literal`.)r)rr r r rwszLiteral.wrappedcCszt|tjr|}nt|tjr&|j}ntdt|j}t|drN||| }t rvt|t rv| tj |j}|S)Nz(context must be a connection or a cursorprepare)rrDZ connectionZcursorrZadaptrhasattrrHZ getquotedrbytesdecodeZ encodingsencoding)rrZconnar'r r r r|s     zLiteral.as_stringN)r rrrr+rrr r r r rGcs rGcs>eZdZdZd fdd ZeddZddZd d ZZ S) PlaceholderaA `Composable` representing a placeholder for query parameters. If the name is specified, generate a named placeholder (e.g. ``%(name)s``), otherwise generate a positional placeholder (e.g. ``%s``). The object is useful to generate SQL queries with a variable number of arguments. Examples:: >>> names = ['foo', 'bar', 'baz'] >>> q1 = sql.SQL("insert into table ({}) values ({})").format( ... sql.SQL(', ').join(map(sql.Identifier, names)), ... sql.SQL(', ').join(sql.Placeholder() * len(names))) >>> print(q1.as_string(conn)) insert into table ("foo", "bar", "baz") values (%s, %s, %s) >>> q2 = sql.SQL("insert into table ({}) values ({})").format( ... sql.SQL(', ').join(map(sql.Identifier, names)), ... sql.SQL(', ').join(map(sql.Placeholder, names))) >>> print(q2.as_string(conn)) insert into table ("foo", "bar", "baz") values (%(foo)s, %(bar)s, %(baz)s) NcsHt|tr d|kr4td|n|dk r4td|tt||dS)N)zinvalid name: %rz'expected string or None as name, got %r)rrr1rr!rNr )rr6)r r r r s   zPlaceholder.__init__cCs|jS)zThe name of the `!Placeholder`.)r)rr r r r6szPlaceholder.namecCsd|jdk r|jndfS)NzPlaceholder(%r)r%)r)rr r r rszPlaceholder.__repr__cCs|jdk rd|jSdSdS)Nz%%(%s)sz%s)r)rrr r r rs  zPlaceholder.as_string)N) r rrrr r+r6rrr,r r )r r rNs  rNNULLDEFAULT)rr-Zpsycopg2rrDZpsycopg2.compatrrZ Formatterr/objectrrr*r<rGrNrPrQr r r r s 3IA-6