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 `!obj` string doesn't undergo any form of escaping, so it is not
| 175 | |
| 176 | |
| 177 | class SQL(Composable): |
| 178 | """ |
| 179 | A `Composable` representing a snippet of SQL statement. |
| 180 | |
| 181 | `!SQL` exposes `join()` and `format()` methods useful to create a template |
| 182 | where to merge variable parts of a query (for instance field or table |
| 183 | names). |
| 184 | |
| 185 | The `!obj` string doesn't undergo any form of escaping, so it is not |
| 186 | suitable to represent variable identifiers or values: you should only use |
| 187 | it to pass constant strings representing templates or snippets of SQL |
| 188 | statements; use other objects such as `Identifier` or `Literal` to |
| 189 | represent variable parts. |
| 190 | |
| 191 | `!SQL` objects can be passed directly to `~psycopg.Cursor.execute()`, |
| 192 | `~psycopg.Cursor.executemany()`, `~psycopg.Cursor.copy()` in place of the |
| 193 | query string. |
| 194 | |
| 195 | Example:: |
| 196 | |
| 197 | >>> query = sql.SQL("SELECT {0} FROM {1}").format( |
| 198 | ... sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]), |
| 199 | ... sql.Identifier('table')) |
| 200 | >>> print(query.as_string(conn)) |
| 201 | SELECT "foo", "bar" FROM "table" |
| 202 | """ |
| 203 | |
| 204 | _obj: LiteralString |
| 205 | _formatter = string.Formatter() |
| 206 | |
| 207 | def __init__(self, obj: LiteralString): |
| 208 | super().__init__(obj) |
| 209 | if not isinstance(obj, str): |
| 210 | raise TypeError(f"SQL values must be strings, got {obj!r} instead") |
| 211 | |
| 212 | def as_string(self, context: AdaptContext | None = None) -> str: |
| 213 | return self._obj |
| 214 | |
| 215 | def as_bytes(self, context: AdaptContext | None = None) -> bytes: |
| 216 | conn = context.connection if context else None |
| 217 | enc = conn_encoding(conn) |
| 218 | return self._obj.encode(enc) |
| 219 | |
| 220 | def format(self, *args: Any, **kwargs: Any) -> Composed: |
| 221 | """ |
| 222 | Merge `Composable` objects into a template. |
| 223 | |
| 224 | :param args: parameters to replace to numbered (``{0}``, ``{1}``) or |
| 225 | auto-numbered (``{}``) placeholders |
| 226 | :param kwargs: parameters to replace to named (``{name}``) placeholders |
| 227 | :return: the union of the `!SQL` string with placeholders replaced |
| 228 | :rtype: `Composed` |
| 229 | |
| 230 | The method is similar to the Python `str.format()` method: the string |
| 231 | template supports auto-numbered (``{}``), numbered (``{0}``, |
| 232 | ``{1}``...), and named placeholders (``{name}``), with positional |
| 233 | arguments replacing the numbered placeholders and keywords replacing |
| 234 | the named ones. However placeholder modifiers (``{0!r}``, ``{0:<10}``) |
no outgoing calls
no test coverage detected