kvesteri / sqlalchemy-utils

Various utility functions and datatypes for SQLAlchemy.
Other
1.23k stars 317 forks source link

With method ```create_view``` to construct a view ORM, then how to create corresponding database view? #742

Open flyly0755 opened 1 month ago

flyly0755 commented 1 month ago
from clickhouse_sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy import Integer, String
from clickhouse_sqlalchemy import engines
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import select
from sqlalchemy_utils import create_view

Base = declarative_base()

class TableTest(Base):
    __tablename__ = 'tabletest'
    id = Column(Integer, primary_key=True)
    testcontent = Column(String)
    remark = Column(String)
    __table_args__ = (
        engines.MergeTree(order_by='id', primary_key='id'),
        {'comment': 'table used for testing'}
    )

viewlist = [] 
viewlist.extend([
    TableTest.id.label('id'),
    TableTest.testcontent.label('testcontent'),
    TableTest.remark.label('remark'),
])
stmt_view = select(viewlist)
cvView = create_view('viewTest', stmt_view, Base.metadata)

class ViewTest(Base):
    __tablename__ = 'viewTest'
    __table__ = cvView
    __table_args__ = {'comment': 'view used for testing'}

# clickhouse machine info
ckuser = "ckuser"
ckpwd = "ckpassword"
ckip = "ckhost"
ckport = "8123"
ckdbname = 'ckdb'

uri = f"clickhouse://{ckuser}:{ckpwd}@" \
      f"{ckip}:{ckport}/{ckdbname}"
engine = create_engine(uri, echo=False)
DBsession = sessionmaker(bind=engine)
session = DBsession()
print(session)
session.execute('SELECT 1')
# TableTest.__table__.create(engine) # success create table tableTest
# ViewTest.__table__.create(engine)  # sqlalchemy.exc.CompileError: No engine for table 'viewTest'
Base.metadata.create_all(bind=engine)  # success create both table tableTest and view viewTest
session.close()

So after creating TableTest with code

TableTest.__table__.create(engine)

How to individually create view ViewTest?

gaiuscosades commented 3 weeks ago

I'd like to bump this, and would like to add that it also maybe a bug:

ViewTest.__table__.create(engine)

This code should be useable as a View is just a special type of Table for sqlalchemy, which is the reason why it gets decalared in a similar way to it using create_view(). But if I execute this, it results in the creation of a table and not a view, which cannot be intended.

In addition the following should work, but results in an error because the view is created not respecting the arguments given using the tables argument.

Base.metadata.create_all(bind=engine, tables=[ViewTest.__table__])

In the same way the view is also created wrongly when executing:

Base.metadata.create_all(bind=engine, tables=[TableTest.__table__])

This has to be a buggy behavior in my understanding.