On 8/15/15 8:07 PM, dbbbit wrote:
we have to execute our sql in limited form in our company,
like `sqlstore.execute('select id from foos where is_foo = %s and
create_time>%', (1, datetime.now())`,
which sqlstore.execute is defined like:
defexecute(self,sql,args=None,executemany=False):
the `sql` param is string type, `args` is a tuple of values
I want to use sqlalchemy core to construct the `sql` and `args`,
is that a way to translate all sqlalchemy's insert(), select() ... to
the given form?
you want to use compile() to produce a Compiled object which then gives
you a string.
This is introduced in the FAQ at
http://docs.sqlalchemy.org/en/rel_1_0/faq/sqlexpressions.html#how-do-i-render-sql-expressions-as-strings-possibly-with-bound-parameters-inlined.
You'll want to use a dialect that has paramstyle='format' since you want
%s with positional. Supposing the MySQL dialect:
from sqlalchemy.dialects import mysql
dialect = mysql.dialect()
stmt = select([table]).where(table.c.bar == 5)
compiled = stmt.compile(dialect=dialect)
sql_string = str(compiled) # or unicode(compiled)
params = compiled.params # this is a dictionary
positional_params = [params[key] for key in compiled.positiontup] #
this is positional
... or if you have the params separate, like a list for executemany
my_params = [{dict1...}, {dict2..}, ...]
positional_params = [
dict((key, paramdict[key]) for key in compiled.positiontup)
for paramdict in my_params
]
now above, what you are *losing* is that SQLAlchemy's datatypes can also
process the values given, which some datatypes need for some DBAPIs. If
you need to get at that then you need to look in compiled.binds, which
is a dictionary of name->BindParam, and in each BindParam is a type
object, e.g. TypeEngine, and for each of those datatypes you need to get
at their processor using type.bind_processor() and then apply it:
for key in my_param_dict:
bind = compiled.binds[key]
type = bind.type
processor = type.bind_processor(dialect)
if processor is not None:
my_param_dict[key] = processor(my_param_dict[key])
again that's only if you need types to take effect for binds.
Then you have the same issue on the result side. I'm not sure what "def
execute()" returns. If it returns a DBAPI cursor, that can be
theoretically sent right to a ResultProxy with your Compiled object and
you can get typing behavior on the result side as well, but it would
need some state built up for it in the form of an ExecutionContext object.
It would also be possible, with a good amount of creativity, to build
your custom "def execute()" right into a fake DBAPI or Dialect object
and have the whole thing transparently operating underneath an ordinary
SQLAlchemy Engine. Whether you stick with the FAQ recipe or get all
the way into this is all about how ambitious you want to be (though
obviously, the best approach of all is just to convince your company
that an artificial "execute()" method is not really worth the
inconvenience of disallowing better tooling).
--
You received this message because you are subscribed to the Google
Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to sqlalchemy+unsubscr...@googlegroups.com
<mailto:sqlalchemy+unsubscr...@googlegroups.com>.
To post to this group, send email to sqlalchemy@googlegroups.com
<mailto:sqlalchemy@googlegroups.com>.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.