summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/compiler.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-10-27 17:41:30 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-10-27 17:41:30 +0000
commit4a4daad81a6c5f987ac6eba0afdaccb3a70554f8 (patch)
treec5d4286d3b318774a518f31a31a66e99286c0a1e /lib/sqlalchemy/sql/compiler.py
parentcba1e9a01ef292a5bb7fdd4e0c62f4f7509f38b9 (diff)
downloadsqlalchemy-4a4daad81a6c5f987ac6eba0afdaccb3a70554f8.tar.gz
- removed regular expression step from most statement compilations.
also fixes [ticket:833] - inlining on PG with_returning() call - extra options added for profiling
Diffstat (limited to 'lib/sqlalchemy/sql/compiler.py')
-rw-r--r--lib/sqlalchemy/sql/compiler.py64
1 files changed, 27 insertions, 37 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index f2627eb85..e662f8e99 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -43,6 +43,15 @@ BIND_PARAMS = re.compile(r'(?<![:\w\$\x5c]):([\w\$]+)(?![:\w\$])', re.UNICODE)
BIND_PARAMS_ESC = re.compile(r'\x5c(:[\w\$]+)(?![:\w\$])', re.UNICODE)
ANONYMOUS_LABEL = re.compile(r'{ANON (-?\d+) (.*)}')
+BIND_TEMPLATES = {
+ 'pyformat':"%%(%(name)s)s",
+ 'qmark':"?",
+ 'format':"%%s",
+ 'numeric':"%(position)s",
+ 'named':":%(name)s"
+}
+
+
OPERATORS = {
operators.and_ : 'AND',
operators.or_ : 'OR',
@@ -132,15 +141,14 @@ class DefaultCompiler(engine.Compiled, visitors.ClauseVisitor):
# for aliases
self.generated_ids = {}
- # default formatting style for bind parameters
- self.bindtemplate = ":%s"
-
# paramstyle from the dialect (comes from DB-API)
self.paramstyle = self.dialect.paramstyle
# true if the paramstyle is positional
self.positional = self.dialect.positional
+ self.bindtemplate = BIND_TEMPLATES[self.paramstyle]
+
# a list of the compiled's bind parameter names, used to help
# formulate a positional argument list
self.positiontup = []
@@ -148,38 +156,8 @@ class DefaultCompiler(engine.Compiled, visitors.ClauseVisitor):
# an IdentifierPreparer that formats the quoting of identifiers
self.preparer = self.dialect.identifier_preparer
-
- def after_compile(self):
- # this re will search for params like :param
- # it has a negative lookbehind for an extra ':' so that it doesnt match
- # postgres '::text' tokens
- text = self.string
- if ':' not in text:
- return
-
- if self.paramstyle=='pyformat':
- text = BIND_PARAMS.sub(lambda m:'%(' + m.group(1) +')s', text)
- elif self.positional:
- params = BIND_PARAMS.finditer(text)
- for p in params:
- self.positiontup.append(p.group(1))
- if self.paramstyle=='qmark':
- text = BIND_PARAMS.sub('?', text)
- elif self.paramstyle=='format':
- text = BIND_PARAMS.sub('%s', text)
- elif self.paramstyle=='numeric':
- i = [0]
- def getnum(x):
- i[0] += 1
- return str(i[0])
- text = BIND_PARAMS.sub(getnum, text)
- # un-escape any \:params
- text = BIND_PARAMS_ESC.sub(lambda m: m.group(1), text)
- self.string = text
-
def compile(self):
self.string = self.process(self.statement)
- self.after_compile()
def process(self, obj, stack=None, **kwargs):
if stack:
@@ -291,11 +269,20 @@ class DefaultCompiler(engine.Compiled, visitors.ClauseVisitor):
return typeclause.type.dialect_impl(self.dialect).get_col_spec()
def visit_textclause(self, textclause, **kwargs):
- for bind in textclause.bindparams.values():
- self.process(bind)
if textclause.typemap is not None:
self.typemap.update(textclause.typemap)
- return textclause.text
+
+ def do_bindparam(m):
+ name = m.group(1)
+ if name in textclause.bindparams:
+ return self.process(textclause.bindparams[name])
+ else:
+ return self.bindparam_string(name)
+
+ # un-escape any \:params
+ return BIND_PARAMS_ESC.sub(lambda m: m.group(1),
+ BIND_PARAMS.sub(do_bindparam, textclause.text)
+ )
def visit_null(self, null, **kwargs):
return 'NULL'
@@ -437,7 +424,10 @@ class DefaultCompiler(engine.Compiled, visitors.ClauseVisitor):
return ANONYMOUS_LABEL.sub(self._process_anon, name)
def bindparam_string(self, name):
- return self.bindtemplate % name
+ if self.positional:
+ self.positiontup.append(name)
+
+ return self.bindtemplate % {'name':name, 'position':len(self.positiontup)}
def visit_alias(self, alias, asfrom=False, **kwargs):
if asfrom: