Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking for non-existent optional tables

I am using SQLAlchemy + Pyramid to operate on my database. However, there are some optional tables which are not always expected to be present in the DB. So while querying them I try to catch such cases with the NoSuchTableError

try:
    x = session.query(ABC.name.label('sig_name'),func.count('*').label('count_')).join(DEF).join(MNO).filter(MNO.relevance >= relevance_threshold).group_by(DEF.signature).order_by(desc('count_')).all()[:val]
except NoSuchTableError:
    x = [-1,]

But on executing this statement, I get a ProgrammingError

ProgrammingError: (ProgrammingError) (1146, "Table 'db.mno' doesn't exist")

Why does SQLAlchemy raise the more general ProgrammingError instead of the more specific NoSuchTableError? And if this is indeed expected behaviour, how do I ensure the app displays correct information depending on whether tables are present/absent?

EDIT1

Since this is part of my webapp, the model of DB is in models.py (under my pyramid webapp). I do have a setting in my .ini file that asks user to select whether additional tables are available or not. But not trusting the user, I want to be able to check for myself (in the views) whether table exists or not. The contentious table is something like (in models.py)

class MNO(Base):
    __tablename__="mno"
    id=Column(Integer,primary_key=True,autoincrement=True)
    sid=Column(Integer)
    cid=Column(mysql.MSInteger(unsigned=True))
    affectability=Column(Integer)
    cvss_base=Column(Float)
    relevance=Column(Float)
    __table_args__=(ForeignKeyConstraint(['sid','cid',],['def.sid','def.cid',]),UniqueConstraint('sid','cid'),)

How and Where should the check be made so that a variable can be set (preferably during app setup) which tells me whether the tables are present or not?

Note: In this case I would have to try if...else rather than 'ask for forgiveness'

like image 844
RedBaron Avatar asked Jul 01 '26 02:07

RedBaron


1 Answers

According to the sqlalchemy docs, a NoSuchTableError is only thrown when "SQLAlchemy [is] asked to load a table's definition from the database, but the table doesn't exist." You could try loading a table's definition, catching the error there, and doing your query otherwise.

If you want to do things via "asking for forgiveness":

try:
    table = Table(table_name, MetaData(engine)) 
except NoSuchTableError:
    pass

Alternatively, you could just check whether the table exists:

Edit:

Better yet, why don't you use the has_table method:

if engine.dialect.has_table(connection, table_name):
    #do your crazy query

Why don't you use Inspector to grab the table names first?

Maybe something like this:

from sqlalchemy import create_engine
from sqlalchemy.engine import reflection
#whatever code you already have
engine = create_engine('...')
insp = reflection.Inspector.from_engine(engine)
table_name = 'foo'
table_names = insp.get_table_names()
if table_name in table_names:
    x = session.query(ABC.name.label('sig_name'),func.count('*').label('count_')).join(DEF).join(MNO).filter(MNO.relevance >= relevance_threshold).group_by(DEF.signature).order_by(desc('count_')).all()[:val]
like image 98
Nolen Royalty Avatar answered Jul 02 '26 15:07

Nolen Royalty



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!