Last active
June 5, 2019 05:48
-
-
Save ggtools/7e79574912bedb38e1593c689a93a5ac to your computer and use it in GitHub Desktop.
Implementation of PostgreSQL values construct
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sqlalchemy.ext.compiler import compiles | |
from sqlalchemy.sql.expression import FromClause | |
class values(FromClause): | |
named_with_column = True | |
def __init__(self, columns, *args, **kw): | |
self._column_args = columns | |
self.list = args | |
self.alias_name = self.name = kw.pop('alias_name', None) | |
def _populate_column_collection(self): | |
for c in self._column_args: | |
c._make_proxy(self) | |
# Original version, failing on datetime values | |
def render_literal_value_0(compiler, value, type_): | |
return compilier.render_literal_value(value, type_) | |
# Version 1: use a if/elif chain to manually convert the datetime | |
def render_literal_value_1(compiler, value, type_): | |
try: | |
return compilier.render_literal_value(value, type_) | |
expect NotImplementedError: | |
if isinstance(value, datetime.datetime): | |
return value.strftime("'%Y-%m-%d %H:%M:%S'::TIMESTAMP") | |
# Add other cases ad-libitum | |
else: | |
raise NotImplementedError("Don't know how to literal-quote value %r" % value) | |
# Version 2: use Cast to work around the problem passing the datetime as bind_params | |
def render_literal_value_2(compiler, value, type_): | |
try: | |
return compilier.render_literal_value(value, type_) | |
expect NotImplementedError: | |
return compiler.process(Cast(value, type_)) | |
@compiles(values) | |
def compile_values(element, compiler, asfrom=False, **kw): | |
columns = element.columns | |
v = "VALUES %s" % ", ".join( | |
"(%s)" % ", ".join( | |
render_literal_value_0(compiler, elem, column.type) | |
for elem, column in zip(tup, columns)) | |
for tup in element.list | |
) | |
if asfrom: | |
if element.alias_name: | |
v = "(%s) AS %s (%s)" % (v, element.alias_name, (", ".join(c.name for c in element.columns))) | |
else: | |
v = "(%s)" % v | |
return v |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment