[英]Generating Boolean Expressions from Subqueries in SQLAlchemy
I have the following SQLAlchemy models: 我有以下SQLAlchemy模型:
PENDING_STATE = 'pending'
COMPLETE_STATE = 'success'
ERROR_STATE = 'error'
class Assessment(db.Model):
__tablename__ = 'assessments'
id = db.Column(db.Integer, primary_key=True)
state = db.Column(
db.Enum(PENDING_STATE, COMPLETE_STATE, ERROR_STATE,
name='assessment_state'),
default=PENDING_STATE,
nullable=False,
index=True)
test_results = db.relationship("TestResult")
class TestResult(db.Model):
__tablename__ = 'test_results'
name = db.Column(db.String, primary_key=True)
state = db.Column(
db.Enum(PENDING_STATE, COMPLETE_STATE, ERROR_STATE,
name='test_result_state_state'),
default=PENDING_STATE,
nullable=False,
index=True)
assessment_id = db.Column(
db.Integer,
db.ForeignKey(
'assessments.id', onupdate='CASCADE', ondelete='CASCADE'),
primary_key=True)
And I am trying to implement logic to update an assessment to the error state if any of its test results are in the error state and update the assessment to the success state if all of its test results are in the success state. 而且,我正在尝试实现一种逻辑,如果其测试结果中的任何一个处于错误状态,则将评估更新为错误状态;如果其所有测试结果都为成功状态,则将评估更新为成功状态。
I can write raw SQL like this: 我可以这样写原始SQL:
SELECT 'error'
FROM assessments
WHERE assessments.state = 'error' OR 'error' IN (
SELECT test_results.state
FROM test_results
WHERE test_results.assessment_id = 1);
But I don't know how to translate that into SQLAlchemy. 但是我不知道如何将其转换为SQLAlchemy。 I'd think that subquery would be something like:
我认为子查询应该是这样的:
(select([test_results.state]).where(test_results.assessment_id == 1)).in_('error')
but I can't find any way to compare query results against literals like I'm doing in the raw SQL. 但是我找不到像在原始SQL中一样将查询结果与文字进行比较的任何方法。 I swear I must be missing something, but I'm just not seeing a way to write queries which return boolean expressions, which I think is fundamentally what I'm butting up against.
我发誓我一定会错过一些东西,但是我只是没有看到一种写返回布尔表达式的查询的方法,我认为这基本上是我所要面对的。 Just something as simple as:
就像这样简单:
SELECT 'a' = 'b'
Seems to be absent from the documentation. 似乎在文档中没有。
Any ideas on how to express this state change in SQLAlchemy? 关于如何在SQLAlchemy中表达这种状态变化的任何想法? I'd also be perfectly open to rethinking my schemas if it looks like I'm going about this in a silly way.
如果看起来我在以愚蠢的方式进行此操作,我也非常愿意重新考虑自己的模式。
Thanks! 谢谢!
Query below should do it for error
check. 下面的查询应进行
error
检查。 Keep in mind that no rows will be returned in case it is not an eror. 请记住,如果不是错误,将不返回任何行。
q = (db.session.query(literal_column("'error'"))
.select_from(Assessment)
.filter(Assessment.id == sid)
.filter(or_(
Assessment.state == ERROR_STATE,
Assessment.test_results.any(TestResult.state == ERROR_STATE),
)))
If you wish to do similar check for success
, you could find if there is any TestResult
which is not a success
and negate boolean result. 如果你希望做类似的检查
success
,你会发现,如果有任何TestResult
这是不是一个success
和否定布尔结果。
I actually ended up doing this with postgres triggers, which is probably the better way to handle state updates. 实际上,我最终使用postgres触发器完成了此操作,这可能是处理状态更新的更好方法。 So for the error case, I've got:
因此对于错误情况,我有:
sqlalchemy.event.listen(TestResult.__table__, 'after_create', sqlalchemy.DDL("""
CREATE OR REPLACE FUNCTION set_assessment_failure() RETURNS trigger AS $$
BEGIN
UPDATE assessments
SET state='error'
WHERE id=NEW.assessment_id;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER assessment_failure
AFTER INSERT OR UPDATE OF state ON test_results
FOR EACH ROW
WHEN (NEW.state = 'error')
EXECUTE PROCEDURE set_assessment_failure();"""))
And something similar for the 'success' case where I count the number of test results vs the number of successful test results. 对于“成功”情况,我计算测试结果的数量与成功测试结果的数量类似。
Credit to van for answering my question as I asked it, though! 不过,请感谢van回答了我提出的问题! Thanks, I hadn't bumped into relationship.any before.
谢谢,我以前从未接触过关系。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.