1

データベース (Postgres) に次のような関数があります。

create function test_f(a text default '*', b text default '+') returns text as $$
    select a || ' ' || b;
$$ language sql;

Postgres では、名前付きパラメーターを使用して呼び出すことができます。

mytest=> select test_f('a', 'b');                                           
test_f                                                                      
--------                                                                    
a b                                                                         
(1 row)                                                                     

mytest=> select test_f('a');                                                
test_f                                                                      
--------                                                                    
a +                                                                         
(1 row)                                                                     

mytest=> select test_f(b:='a');                                             
test_f                                                                      
--------                                                                    
* a                                                                         
(1 row)                                                                     

SQLAlchemy のfuncconstructを使用して Python から同じことをしたいのですが、func名前付きパラメーターを尊重していないようです:

In [85]: print(sqlalchemy.func.test_f('a', 'b'))                            
test_f(:test_f_1, :test_f_2)                                                

In [86]: print(sqlalchemy.func.test_f('a'))                                 
test_f(:test_f_1)                                                           

In [87]: print(sqlalchemy.func.test_f(a='a'))                               
test_f()                                                                    

何か不足していますか、それともfunc名前付きパラメーターをサポートしていませんか?

4

1 に答える 1

3

Michael Bayer の提案のおかげで、私は自分自身の質問に対する解決策を思いつきました: トリックはSQLAlchemy の compilerといくつかの適切なエスケープを使用することです:

from psycopg2.extensions import adapt as sqlescape                          
import sqlalchemy                                                           
from sqlalchemy import select                                               
from sqlalchemy.ext.compiler import compiles                                
from sqlalchemy.sql.expression import ColumnClause                          


class MyFunc(ColumnClause):                                                 
    def __init__(self, *args, **kwargs):                                    
        self.kwargs = kwargs                                                
        super().__init__(*args)                                             


@compiles(MyFunc)                                                           
def compile_myfunc(element, compiler, **kw):                                
    s = ','.join("%s:=%s" % (k, sqlescape(v)) for k, v in element.kwargs.items())
    return "%s(%s)" % (element.name, s)                                     


def call(engine, func, **kwargs):                                           
    return engine.execute(select([MyFunc(func, **kwargs)]))                 


engine = sqlalchemy.create_engine('postgresql+psycopg2://lbolla@localhost/mytest')
print(call(engine, 'test_f', a='a').scalar())                               
print(call(engine, 'test_f', b='b').scalar())                               
于 2013-03-11T11:15:07.910 に答える