use a join instead of a subquery as sqlite can optimize it better

This commit is contained in:
Damien Elmes 2010-10-26 20:21:59 +09:00
parent c50b7e61cb
commit 9f9841cb22

View file

@ -192,40 +192,43 @@ class Deck(object):
self.rebuildRevCount() self.rebuildRevCount()
self.rebuildNewCount() self.rebuildNewCount()
def cardLimit(self, active, inactive): def cardLimit(self, active, inactive, sql):
yes = parseTags(self.getVar(active)) yes = parseTags(self.getVar(active))
no = parseTags(self.getVar(inactive)) no = parseTags(self.getVar(inactive))
if yes: if yes:
yids = tagIds(self.s, yes).values() yids = tagIds(self.s, yes).values()
nids = tagIds(self.s, no).values() nids = tagIds(self.s, no).values()
return """ repl = (
and id in (select cardId from cardTags where "c.id = ct.cardId and tagId in %s and "
tagId in %s and tagId not in %s)""" % (ids2str(yids), ids2str(nids)) "tagId not in %s and ") % (ids2str(yids), ids2str(nids))
elif no: elif no:
nids = tagIds(self.s, no).values() nids = tagIds(self.s, no).values()
return """ repl = "c.id = ct.cardId and tagId not in %s and " % ids2str(nids)
and id not in (select cardId from cardTags where
tagId in %s)""" % (ids2str(nids))
else: else:
return "" return sql
return sql.replace("from cards c where",
"from cards c, cardTags ct where " + repl)
def _rebuildFailedCount(self): def _rebuildFailedCount(self):
self.failedSoonCount = self.s.scalar(""" self.failedSoonCount = self.s.scalar(
select count(*) from cards where type = 0 self.cardLimit(
and combinedDue < :lim """ + self.cardLimit("revActive", "revInactive"), "revActive", "revInactive",
lim=self.dueCutoff) "select count(*) from cards c where type = 0 "
"and combinedDue < :lim"), lim=self.dueCutoff)
def _rebuildRevCount(self): def _rebuildRevCount(self):
self.revCount = self.s.scalar(""" self.revCount = self.s.scalar(
select count(*) from cards where type = 1 self.cardLimit(
and combinedDue < :lim """ + self.cardLimit("revActive", "revInactive"), "revActive", "revInactive",
lim=self.dueCutoff) "select count(*) from cards c where type = 1 "
"and combinedDue < :lim"), lim=self.dueCutoff)
def _rebuildNewCount(self): def _rebuildNewCount(self):
self.newCount = self.s.scalar(""" self.newCount = self.s.scalar(
select count(*) from cards where type = 2 self.cardLimit(
and combinedDue < :lim """ + self.cardLimit("newActive", "newInactive"), "newActive", "newInactive",
lim=self.dueCutoff) "select count(*) from cards c where type = 2 "
"and combinedDue < :lim"), lim=self.dueCutoff)
self.updateNewCountToday() self.updateNewCountToday()
def _updateNewCountToday(self): def _updateNewCountToday(self):
@ -235,35 +238,32 @@ and combinedDue < :lim """ + self.cardLimit("newActive", "newInactive"),
def _fillFailedQueue(self): def _fillFailedQueue(self):
if self.failedSoonCount and not self.failedQueue: if self.failedSoonCount and not self.failedQueue:
self.failedQueue = self.s.all(""" self.failedQueue = self.s.all(
select id, factId, combinedDue from cards self.cardLimit(
where type = 0 and combinedDue < :lim "revActive", "revInactive", """
%s select c.id, factId, combinedDue from cards c where
order by combinedDue type = 0 and combinedDue < :lim order by combinedDue
limit %d""" % (self.cardLimit("revActive", "revInactive"), limit %d""" % self.queueLimit), lim=self.dueCutoff)
self.queueLimit), lim=self.dueCutoff)
self.failedQueue.reverse() self.failedQueue.reverse()
def _fillRevQueue(self): def _fillRevQueue(self):
if self.revCount and not self.revQueue: if self.revCount and not self.revQueue:
self.revQueue = self.s.all(""" self.revQueue = self.s.all(
select id, factId from cards self.cardLimit(
where type = 1 and combinedDue < :lim "revActive", "revInactive", """
%s select c.id, factId from cards c where
order by %s type = 1 and combinedDue < :lim order by %s
limit %s""" % (self.cardLimit("revActive", "revInactive"), limit %d""" % (self.revOrder(), self.queueLimit)), lim=self.dueCutoff)
self.revOrder(), self.queueLimit), lim=self.dueCutoff)
self.revQueue.reverse() self.revQueue.reverse()
def _fillNewQueue(self): def _fillNewQueue(self):
if self.newCount and not self.newQueue: if self.newCount and not self.newQueue:
self.newQueue = self.s.all(""" self.newQueue = self.s.all(
select id, factId from cards self.cardLimit(
where type = 2 and combinedDue < :lim "newActive", "newInactive", """
%s select c.id, factId from cards c where
order by %s type = 2 and combinedDue < :lim order by %s
limit %s""" % (self.cardLimit("newActive", "newInactive"), limit %d""" % (self.newOrder(), self.queueLimit)), lim=self.dueCutoff)
self.newOrder(), self.queueLimit), lim=self.dueCutoff)
self.newQueue.reverse() self.newQueue.reverse()
def queueNotEmpty(self, queue, fillFunc): def queueNotEmpty(self, queue, fillFunc):