| |
@@ -2,14 +2,16 @@
|
| |
|
| |
import datetime
|
| |
from .base import db
|
| |
- from sqlalchemy import or_, and_
|
| |
- from sqlalchemy.dialects.postgresql import JSONB
|
| |
+ from sqlalchemy import or_, and_, cast
|
| |
+ from sqlalchemy.dialects.postgresql import JSON
|
| |
+ from sqlalchemy.ext.hybrid import hybrid_method
|
| |
+ from .base import json_serializer
|
| |
|
| |
|
| |
class Waiver(db.Model):
|
| |
id = db.Column(db.Integer, primary_key=True)
|
| |
result_id = db.Column(db.Integer, nullable=True)
|
| |
- subject = db.Column(JSONB, nullable=False, index=True)
|
| |
+ subject = db.Column(JSON, nullable=False)
|
| |
testcase = db.Column(db.Text, nullable=False, index=True)
|
| |
username = db.Column(db.String(255), nullable=False)
|
| |
proxied_by = db.Column(db.String(255))
|
| |
@@ -17,6 +19,9 @@
|
| |
waived = db.Column(db.Boolean, nullable=False, default=False)
|
| |
comment = db.Column(db.Text)
|
| |
timestamp = db.Column(db.DateTime, default=datetime.datetime.utcnow)
|
| |
+ __table_args__ = (
|
| |
+ db.Index('ix_waiver_subject', cast(subject, db.Text)),
|
| |
+ )
|
| |
|
| |
def __init__(self, subject, testcase, username, product_version, waived=False,
|
| |
comment=None, proxied_by=None):
|
| |
@@ -37,11 +42,23 @@
|
| |
def by_results(cls, query, results):
|
| |
return query.filter(or_(*[
|
| |
and_(
|
| |
- cls.subject == d['subject'],
|
| |
+ cls.subject_matches(d['subject']),
|
| |
cls.testcase == d['testcase']
|
| |
) if d.get('testcase', None) else
|
| |
and_(
|
| |
- cls.subject == d['subject']
|
| |
+ cls.subject_matches(d['subject']),
|
| |
) if d.get('subject', None) else
|
| |
and_() for d in results
|
| |
]))
|
| |
+
|
| |
+ @hybrid_method
|
| |
+ def subject_matches(self, other_subject):
|
| |
+ return self.subject == other_subject
|
| |
+
|
| |
+ @subject_matches.expression
|
| |
+ def subject_matches(cls, other_subject): # pylint: disable=E0213
|
| |
+ # Postgres JSON type does not actually permit equality comparison.
|
| |
+ # We need to compare textual representations on the database side.
|
| |
+ # Note this won't work if the RHS is a SQL expression, only because
|
| |
+ # I am too lazy to implement that for now.
|
| |
+ return cast(cls.subject, db.Text) == json_serializer(other_subject)
|
| |
We want to stay compatible with Postgres 9.2 which lacks the JSONB
column type.
We can use the older JSON column type instead, but it needs some extra
massaging to allow equality comparisons across JSON values. (JSONB
handles this itself.)
The short version is: we compare JSON values as strings, which means we
also need to ensure the string serialization is always consistent when
we send it to the database. The sort_keys=True argument to JSONEncoder()
gives us that.
Fixes #134.