Function names in SQL can contain pretty much anything, e.g.:

=# create function "A Bug?"(integer) returns integer as $$ select $1; $$ 
language sql;
CREATE FUNCTION

But when attempting to use the function from SQLAlchemy:

from sqlalchemy.sql.expression import func
bug = getattr(func, "A Bug?")(1)
session.query(bug).all()

ProgrammingError: (ProgrammingError) syntax error at or near "?"
LINE 1: SELECT A Bug?(1) AS "A Bug?_1"
 'SELECT A Bug?(%(A Bug?_2)s) AS "A Bug?_1"' {'A Bug?_2': 1}

-Ryan P. Kelly

-- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index dd2a6e0..ada56c6 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -603,7 +603,10 @@ class SQLCompiler(engine.Compiled):
         if disp:
             return disp(func, **kwargs)
         else:
-            name = FUNCTIONS.get(func.__class__, func.name + "%(expr)s")
+            name = FUNCTIONS.get(
+                func.__class__,
+                self.preparer.quote(func.name, None) + "%(expr)s"
+            )
             return ".".join(list(func.packagenames) + [name]) % \
                             {'expr': self.function_argspec(func, **kwargs)}
 
diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py
index 473a422..6ea4d2a 100644
--- a/test/sql/test_compiler.py
+++ b/test/sql/test_compiler.py
@@ -2481,6 +2481,49 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL):
             and_, ("a",), ("b",)
         )
 
+    def test_func(self):
+        f1 = func.somefunc(1)
+        self.assert_compile(
+            select([f1]),
+            "SELECT somefunc(:somefunc_2) AS somefunc_1",
+        )
+        self.assert_compile(
+            select([f1.label("f1")]),
+            "SELECT somefunc(:somefunc_1) AS f1",
+        )
+
+        f2 = func.somefunc(table1.c.name)
+        self.assert_compile(
+            select([f2]),
+            "SELECT somefunc(mytable.name) AS somefunc_1 FROM mytable",
+        )
+        self.assert_compile(
+            select([f2.label("f2")]),
+            "SELECT somefunc(mytable.name) AS f2 FROM mytable",
+        )
+
+        f3 = getattr(func, "Needs Quotes?")(table1.c.myid)
+        self.assert_compile(
+            select([f3]),
+            'SELECT "Needs Quotes?"(mytable.myid) AS "Needs Quotes?_1" FROM '
+            'mytable'
+        )
+        self.assert_compile(
+            select([f3.label("f3")]),
+            'SELECT "Needs Quotes?"(mytable.myid) AS f3 FROM mytable',
+        )
+
+        f4 = getattr(func, "query from pg_stat_activity; --")()
+        self.assert_compile(
+            select([f4]),
+            'SELECT "query from pg_stat_activity; --"() AS "query from '
+            'pg_stat_activity; --_1"',
+        )
+        self.assert_compile(
+            select([f4.label("f4")]),
+            'SELECT "query from pg_stat_activity; --"(mytable.myid) AS f4'
+        )
+
 
 class KwargPropagationTest(fixtures.TestBase):
 

Reply via email to