support for dotted function name

Issue #115 resolved
Former user created an issue

Allow calling functions with multiple name parts:

select([func.mypkg.myfun(tab.c.id)](func.mypkg.myfun(tab.c.id)))

to produce:

select mypkg.myfun(tab.id) from tab

Here is the patch to do just that:

Index: lib/sqlalchemy/engine.py
===================================================================
--- lib/sqlalchemy/engine.py    (revision 1148)
+++ lib/sqlalchemy/engine.py    (working copy)
@@ -169,8 +169,17 @@
             return default.arg()
         else:
             return default.arg
-

+class FunctionGateway(object):
+    def __init__(self, engine):
+        self.__engine = engine
+        self.__names = []
+    def __getattr__(self, name):
+        self.__names.append(name)
+        return self
+    def __call__(self, *c, **kwargs):
+        return sql.Function(".".join(self.__names), engine=self.__engine, *c, **kwargs)
+
 class SQLEngine(schema.SchemaEngine):
     """
     The central "database" object used by an application.  Subclasses of this object is used
@@ -280,10 +289,7 @@
         return typeobj

     def _func(self):
-        class FunctionGateway(object):
-            def __getattr__(s, name):
-                return lambda *c, **kwargs: sql.Function(name, engine=self, *c, **kwargs)
-        return FunctionGateway()
+        return FunctionGateway(self)
     func = property(_func)

     def text(self, text, *args, **kwargs):

Comments (5)

  1. Mike Bayer repo owner

    thanks for contributing this. check out what I did in changeset:1149. the 'func' keyword is a standalone keyword in the SQL package as well. also I modified to keep the "package" names separate from the "function name" so that a bind param name could be more easily generated, and its generally good karma to keep data in a componentized form until the "string compilation" occurs at query compile time. added unit tests for standalone/off the engine funcs with/without package names/bind parameters.

  2. Former user Account Deleted
    • removed status
    • changed status to open

    Nice work, I was completely unaware of the number of changes needed.

    However, when I use it like default=func.some_seq.nextval(), I get errors (Oracle):

    class Tab(ActiveMapper):
        class mapping:
            __table__  = 'tab'
            id         = column(Integer, primary_key=True, default=func.some_seq.nextval())
    

    It generates:

    SELECT nextval \nFROM DUAL
    
  3. Former user Account Deleted
    • removed status
    • changed status to open

    Now it generates

    SQLError: (DatabaseError) ORA-02287: sequence number not allowed here
     'SELECT cc_uvoz_kolone_seq.nextval() \nFROM DUAL' {}
    

    In Oracle, function without parameters is called without parentheses.

  4. Log in to comment