From 71a891f4280a45f5e337b2e7cf4943cd7f8c54cf Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Aug 12 2020 15:34:43 +0000 Subject: ensure that cursors are closed in QueryProcessor.iterate() By using try..finally here, we ensure the cursor cleanup is performed even if the generator is not exhausted before being garbage collected. Fixes https://pagure.io/koji/issue/2435 --- diff --git a/hub/kojihub.py b/hub/kojihub.py index fb4d887..441094a 100644 --- a/hub/kojihub.py +++ b/hub/kojihub.py @@ -9158,28 +9158,30 @@ SELECT %(col_str)s c = context.cnx.cursor() c.execute(query, values) c.close() - query = "FETCH %i FROM %s" % (chunksize, cname) - while True: - if as_list: - if self.transform is None: - buf = _fetchMulti(query, {}) + try: + query = "FETCH %i FROM %s" % (chunksize, cname) + while True: + if as_list: + if self.transform is None: + buf = _fetchMulti(query, {}) + else: + # if we're transforming, generate the dicts so the transform can modify + buf = _multiRow(query, self.values, fields) + buf = [self.transform(row) for row in buf] + # and then convert back to lists + buf = [[row[f] for f in fields] for row in buf] else: - # if we're transforming, generate the dicts so the transform can modify - buf = _multiRow(query, self.values, fields) - buf = [self.transform(row) for row in buf] - # and then convert back to lists - buf = [[row[f] for f in fields] for row in buf] - else: - buf = _multiRow(query, {}, fields) - if self.transform is not None: - buf = [self.transform(row) for row in buf] - if not buf: - break - for row in buf: - yield row - c = context.cnx.cursor() - c.execute("CLOSE %s" % cname) - c.close() + buf = _multiRow(query, {}, fields) + if self.transform is not None: + buf = [self.transform(row) for row in buf] + if not buf: + break + for row in buf: + yield row + finally: + c = context.cnx.cursor() + c.execute("CLOSE %s" % cname) + c.close() def executeOne(self, strict=False): results = self.execute()