import re
def to_positional(func, _pattern=re.compile(r"'(?:''|[^'])*'|--.*|:(\w+)")):
def execute(operation, namespace):
def replacer(match):
if name := match[1]:
params.append(namespace[name])
return '?'
return match[0]
params = []
return func(_pattern.sub(replacer, operation), params)
return execute
sql = """\
UPDATE products
SET
name=:name,
price=:price,
description=':description ''' || :description || ''''
WHERE id=:id; -- :comment
"""
data = {'id': 123, 'name': 'foo', 'price': 99.99, 'description': 'foo description'}
to_positional(print)(sql, data)
aW1wb3J0IHJlCgpkZWYgdG9fcG9zaXRpb25hbChmdW5jLCBfcGF0dGVybj1yZS5jb21waWxlKHIiJyg/OicnfFteJ10pKid8LS0uKnw6KFx3KykiKSk6CiAgICBkZWYgZXhlY3V0ZShvcGVyYXRpb24sIG5hbWVzcGFjZSk6CiAgICAgICAgZGVmIHJlcGxhY2VyKG1hdGNoKToKICAgICAgICAgICAgaWYgbmFtZSA6PSBtYXRjaFsxXToKICAgICAgICAgICAgICAgIHBhcmFtcy5hcHBlbmQobmFtZXNwYWNlW25hbWVdKQogICAgICAgICAgICAgICAgcmV0dXJuICc/JwogICAgICAgICAgICByZXR1cm4gbWF0Y2hbMF0KICAgICAgICBwYXJhbXMgPSBbXQogICAgICAgIHJldHVybiBmdW5jKF9wYXR0ZXJuLnN1YihyZXBsYWNlciwgb3BlcmF0aW9uKSwgcGFyYW1zKQogICAgcmV0dXJuIGV4ZWN1dGUKCnNxbCA9ICIiIlwKVVBEQVRFIHByb2R1Y3RzClNFVAogICAgbmFtZT06bmFtZSwKICAgIHByaWNlPTpwcmljZSwKICAgIGRlc2NyaXB0aW9uPSc6ZGVzY3JpcHRpb24gJycnIHx8IDpkZXNjcmlwdGlvbiB8fCAnJycnCldIRVJFIGlkPTppZDsgLS0gOmNvbW1lbnQKIiIiCmRhdGEgPSB7J2lkJzogMTIzLCAnbmFtZSc6ICdmb28nLCAncHJpY2UnOiA5OS45OSwgJ2Rlc2NyaXB0aW9uJzogJ2ZvbyBkZXNjcmlwdGlvbid9CnRvX3Bvc2l0aW9uYWwocHJpbnQpKHNxbCwgZGF0YSk=