Skip to content

Instantly share code, notes, and snippets.

@cbsmith
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbsmith/177e5572de614eb61279 to your computer and use it in GitHub Desktop.
Save cbsmith/177e5572de614eb61279 to your computer and use it in GitHub Desktop.
An example of how one could wrap pyodbc's wildcard prepared statements with Python's format string to have keyword based prepared statements.
from string import Formatter
import sys
def keywords_to_questionmarks(format_string, *args, **kwargs):
'''Convert a format string keyword formatted query to a ? wildcarded prepared statement
that is pyodbc compatible, along with the args tuple to pass to it.
* format_string: Python format compatible representation of a query
* args: positional args for the format string
* kwargs: keyword args for the format string
returns: a pyodbc compatible format string followed by the args tuple to pass with it
'''
varargs = [] # there are prettier ways to do this, but this is easier to read
def query_string_generator(template, *args, **kwargs):
'''Helper function that generates the pieces of the query string.'''
args_iter = iter(args)
f = Formatter()
for literal, field_name, format_spec, conversion in f.parse(template):
yield literal
if field_name is not None:
yield '?'
if field_name:
val = kwargs[field_name]
varargs.append(val)
else:
varargs.append(next(args_iter))
query_string = ''.join(query_string_generator(format_string, *args, **kwargs))
return query_string, tuple(varargs)
def main(args):
'''Sample driving of the function.
Output with no args is:
foo is testing ?? and ?? with ?
Cursor args:
0: 21
1: varargs_param
2: thirty
3: thirty
4: 21
'''
format_string = args[1] if len(args) > 1 else 'foo is testing {foo}{} and {bar}{bar} with {foo}'
query_string, args = keywords_to_questionmarks(format_string, 'varargs_param', foo=21, bar='thirty')
print(query_string)
print('Cursor args:')
for i, arg in enumerate(args):
print('\t{}: {}'.format(i, arg))
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment