-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for #1991 causes DoesNotExist error during row iteration #2115
Comments
SELECT
COALESCE("t1"."guid", "t2"."guid") AS "guid",
COALESCE("t1"."remedy_group", ?) AS "name",
"t3"."id",
COUNT("t2"."host_id") AS "count",
JSON_GROUP_ARRAY("t2"."host_id") AS "host_ids"
FROM "vulnerability" AS "t2"
INNER JOIN "plugin" AS "t3" ON ("t2"."plugin_id" = "t3"."id")
INNER JOIN "query" AS "t4" ON ("t2"."query_id" = "t4"."id")
INNER JOIN "host" AS "t5" ON ("t2"."host_id" = "t5"."ip_address")
LEFT OUTER JOIN "team" AS "t1" ON ("t1"."name" = (
SELECT "t1"."name" FROM "team" AS "t1"
WHERE (
("t1"."name" = TRIM(json_extract("t5"."tags", ?))) OR
("t1"."remedy_group" = TRIM(json_extract("t5"."tags", ?)))) LIMIT ?
))
WHERE ((
("t2"."remediation_group_id" = ?) AND
("t4"."process" IN (?, ?))) AND
("t5"."state" != ?))
GROUP BY
COALESCE("t1"."guid", "t2"."guid"),
COALESCE("t1"."remedy_group", ?),
"t3"."id"
ORDER BY COALESCE("t1"."guid", "t2"."guid"), COALESCE("t1"."remedy_group", ?), "t3"."id" |
Does one of those models have a primary key that is a foreign-key to a different table? Is there any way you can provide a minimal way to reproduce this issue? At the very least subtract from this example until you can isolate the minimal query that reproduces the problem? |
How would this happen? The whole thing with referential integrity is that this should not occur. |
Going through the stack trace, I'll show you my thoughts: We're checking if an instance belongs to a set/dict, so we need its hash, which consists of the class and primary-key value:
The
It looks like you've got a composite primary-key...Why do people do this?!
One part of the composite pk is also a foreign-key?
Missing the part we need:
|
In your composite primary-key that also contains a foreign-key, try changing the foreign-key part to be the "safe-name" of the FK rather than the FK field itself: # Change this:
primary_key = CompositeKey('host', 'other_field')
# To this:
primary_key = CompositeKey('host_id', 'other_field') Try that out and let me know if it fixes the problem and works.
Active record ORMs do not work well with composite pks. Try using a regular autoincrement / uuid in the future and just put a unique constraint on the columns you need to guarantee are unique. You'll have a much better time. |
@brandond - can you please take a look at my latest comment and provide additional info? |
I have been able to reproduce the issue by adding the following code to tests/models.py: class Neighbourhood(TestModel):
name = CharField()
city = ForeignKeyField(City)
class Meta:
primary_key = CompositeKey('name', 'city')
class TestCompositePKwithFK(ModelTestCase):
@requires_models(City, Neighbourhood)
def test_join_query(self):
city = City.create(name='city')
neighbourhood = Neighbourhood.create(name='n1',city=city)
query = (Neighbourhood
.select(
Neighbourhood.name,
City.name
)
.join(City).where(
Neighbourhood.name == 'n1'
) )
res = query.get()
self.assertEqual(res.name,'n1')
self.assertEqual(res.city.name, 'city') I am not sure of what you mean with the safe-name of the FK. Replacing "city" by "city_id" in the CompositeKey declaration causes a KeyError at database creation time |
You're probably going to hate me for this, but here's a subsection of the model code. I have the business logic in a subclass of RemediationGroupBase, so self.vulnerabilities hits the backref to the Vulnerability model which does indeed have a composite pk. class RemediationGroupBase(ModelBase):
"""Peewee model class representing persistent data associated with a Tenable asset group"""
id = IntegerField(verbose_name='Group ID', primary_key=True)
name = CharField(verbose_name='Group Name')
guid = CharField(verbose_name='Template GUID')
mid_tier = CharField(verbose_name='Remedy Mid-Tier')
process = CharField(verbose_name='Process')
class Meta:
without_rowid = True
table_name = 'remediation_group'
class Vulnerability(ModelBase):
"""Peewee model class representing a single Vulnerability finding"""
last_seen = DateTimeField(verbose_name='Last Seen Date')
first_seen = DateTimeField(verbose_name='First Seen Date')
plugin_text = CompressedField(verbose_name='Plugin Text', compression_level=9)
netbios_name = CharField(verbose_name='NetBIOS Name')
mac_address = CharField(verbose_name='MAC Address')
repository = CharField(verbose_name='Repository')
port = IntegerField(verbose_name='Port')
dns_name = CharField(verbose_name='DNS Name')
protocol = CharField(verbose_name='Protocol')
host = ForeignKeyField(verbose_name='Host', model=Host, backref='vulnerabilities')
plugin = ForeignKeyField(verbose_name='Plugin', model=Plugin, backref='vulnerabilities')
remediation_group = ForeignKeyField(verbose_name='Remediation Group', model=RemediationGroupBase, backref='vulnerabilities')
query = ForeignKeyField(verbose_name='Query ID', model=Query, backref='vulnerabilities')
guid = CharField(verbose_name='Query Template GUID')
patched = BooleanField(verbose_name='Patched', default=False)
class Meta:
without_rowid = True
primary_key = CompositeKey('host', 'port', 'protocol', 'plugin', 'first_seen') I'm using a composite PK because I'm bulk-loading denormalized data from a 3rd party API and just use insert().on_conflict_replace() to deduplicate rows. I'll try replacing 'host' with 'host_id', etc in the CompositeKey and see if that makes it happier. |
As @Nurbel mentioned, using the safe name causes a KeyError on table creation:
|
Thanks for the info - I'll get to the bottom of this. |
I'll give that change a try, but the tests have all failed? |
I'll fix the tests, thanks. |
I have a rather large cross-model join query that started throwing an exception after updating from 3.9.6 to 3.13.1. This appears to be caused by the fix for #1991 .
The query is:
The resulting query SQL that gets logged is:
The exception is:
It's failing in the iterator, without any iterations of the for loop running. I am guessing I somehow have a Vulnerability with a host_id set to a value that doesn't have a corresponding PK in the Host table, but I can't even try to track that down because it's blowing up the iterator immediately.
The text was updated successfully, but these errors were encountered: