我试图让sqlalchemy创建一个递归视图。如果视图已经创建,代码似乎适用于查询,但在尝试创建视图时会抛出错误。
sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)语法错误在" AS" 第1行:创建RECURSIVE VIEW device_type_hierarchy AS无 ^ [SQL:' CREATE RECURSIVE VIEW device_type_hierarchy AS None']
selectable中必定存在导致语句无法编译的内容,但我无法看到它。我有一个类似的工厂,它创建一个物化视图,它工作正常。
有什么想法吗?
recursive_view_factory.py
# Example from https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/Views
from sqlalchemy.ext import compiler
from sqlalchemy.schema import DDLElement
from sqlalchemy.sql import table
import sqlalchemy as db
class CreateRecursiveView(DDLElement):
def __init__(self, name, selectable):
self.name = name
self.selectable = selectable
class DropRecursiveView(DDLElement):
def __init__(self, name):
self.name = name
@compiler.compiles(CreateRecursiveView)
def compile(element, compiler, **kw):
return "CREATE RECURSIVE VIEW %s AS %s" % (element.name, compiler.sql_compiler.process(element.selectable))
@compiler.compiles(DropRecursiveView)
def compile(element, compiler, **kw):
return "DROP VIEW %s" % (element.name)
def recursive_view(metadata, name, selectable):
#_mt = db.MetaData() # temp metadata just for initial Table object creation
#t = db.Table(name, _mt)
t = table(name)
for c in selectable.c:
c._make_proxy(t)
db.event.listen(metadata,
"after_create",
CreateRecursiveView(name, selectable)
)
db.event.listen(metadata,
"before_drop",
DropRecursiveView(name)
)
return t
model.py
class TDeviceType(Base):
__tablename__ = 'tDeviceType'
label = 'Device Type'
plural = 'Device Types'
ixDeviceType = Column(Integer, primary_key=True)
ixParentDeviceType = Column(Integer, ForeignKey('tDeviceType.ixDeviceType'), nullable=True)
sDeviceType = Column(Unicode(255),
info={'label' : 'Device Type'})
class RVDeviceTypeHierarchy(Base):
included_devices = (select([TDeviceType.ixDeviceType.label('ixDeviceType'),
TDeviceType.ixParentDeviceType.label('ixParentDeviceType'),
TDeviceType.sDeviceType.label('sDeviceType'),
cast(func.row_number().over(partition_by=TDeviceType.ixParentDeviceType,
order_by=TDeviceType.sDeviceType),
Unicode).label('path')])
.select_from(TDeviceType)
.where(TDeviceType.ixParentDeviceType is None)
.cte(name="device_type_hierarchy", recursive=True))
incl_alias = included_devices.alias()
dt_alias = orm.aliased(TDeviceType, name='i')
dth = (included_devices.union_all(
select([dt_alias.ixDeviceType.label('ixDeviceType'),
dt_alias.ixParentDeviceType.label('ixParentDeviceType'),
dt_alias.sDeviceType.label('sDeviceType'),
func.concat(included_devices.c.path,
cast(func.row_number().over(partition_by=dt_alias.ixParentDeviceType,
order_by=dt_alias.sDeviceType),
Unicode)).label('path')])
.select_from(join(dt_alias,
included_devices,
included_devices.c.ixDeviceType == dt_alias.ixParentDeviceType))))
__table__ = recursive_view(metadata,
"device_type_hierarchy",
dth)