diff --git a/anki/deck.py b/anki/deck.py index e49a474f3..5483a5e01 100644 --- a/anki/deck.py +++ b/anki/deck.py @@ -1933,13 +1933,13 @@ and cards.factId = facts.id""") tag = tag.replace("*", "%") if "%" in tag: ids = self.db.column0( - "select id from tags where tag like :tag", tag=tag) + "select id from tags where name like :tag", tag=tag) if search == "and" and not ids: return [] tagIds.append(ids) else: id = self.db.scalar( - "select id from tags where tag = :tag", tag=tag) + "select id from tags where name = :tag", tag=tag) if search == "and" and not id: return [] tagIds.append(id) @@ -1962,7 +1962,7 @@ and cards.factId = facts.id""") return self.db.column0(q) def allTags(self): - return self.db.column0("select tag from tags order by tag") + return self.db.column0("select name from tags order by name") def allTags_(self, where=""): t = self.db.column0("select tags from facts %s" % where) @@ -2034,7 +2034,7 @@ facts.modelId = :id""", id=modelId)) if d: self.db.statements(""" insert into cardTags -(cardId, tagId, src) values +(cardId, tagId, type) values (:cardId, :tagId, :src)""", d) self.deleteUnusedTags() @@ -2527,7 +2527,7 @@ select cards.id from cards, facts where facts.tags = '' and cards.factId = facts else: token = token.replace("*", "%") ids = self.db.column0(""" -select id from tags where tag like :tag escape '\\'""", tag=token) +select id from tags where name like :tag escape '\\'""", tag=token) tquery += """ select cardId from cardTags where cardTags.tagId in %s""" % ids2str(ids) elif type == SEARCH_TYPE: @@ -2574,7 +2574,7 @@ select cardId from cardTags where cardTags.tagId in %s""" % ids2str(ids) elif type == SEARCH_CARD: token = token.replace("*", "%") ids = self.db.column0(""" -select id from tags where tag like :tag escape '\\'""", tag=token) +select id from tags where name like :tag escape '\\'""", tag=token) if isNeg: if cmquery['neg']: cmquery['neg'] += " intersect " @@ -3108,7 +3108,7 @@ where id in %s""" % ids2str(ids)): f['Answer'] = repl(a) try: f.tags = self.db.scalar(""" -select group_concat(tag, " ") from tags t, cardTags ct +select group_concat(name, " ") from tags t, cardTags ct where cardId = :cid and ct.tagId = t.id""", cid=id) or u"" except: raise Exception("Your sqlite is too old.") diff --git a/anki/tags.py b/anki/tags.py index 8f75432c3..2f57f598a 100644 --- a/anki/tags.py +++ b/anki/tags.py @@ -4,51 +4,46 @@ from anki.db import * -#src 0 = fact -#src 1 = model -#src 2 = card model - -# Tables -########################################################################## - -# priority is no longer used +# Type: 0=fact, 1=model, 2=template +# Priority: -100 to 100 +# older sqlalchemy versions didn't support collate for sqlite, so we do it +# manually def initTagTables(s): try: - s.statement(""" + s.execute(""" create table tags ( id integer not null, -tag text not null collate nocase, -priority integer not null default 2, +name text not null collate nocase unique, +priority integer not null default 0, primary key(id))""") - s.statement(""" + s.execute(""" create table cardTags ( -id integer not null, cardId integer not null, tagId integer not null, -src integer not null, -primary key(id))""") +type integer not null, +primary key(tagId, cardId))""") except: pass def tagId(s, tag, create=True): "Return ID for tag, creating if necessary." - id = s.scalar("select id from tags where tag = :tag", tag=tag) + id = s.scalar("select id from tags where name = :tag", tag=tag) if id or not create: return id s.statement(""" insert or ignore into tags -(tag) values (:tag)""", tag=tag) - return s.scalar("select id from tags where tag = :tag", tag=tag) +(name) values (:tag)""", tag=tag) + return s.scalar("select id from tags where name = :tag", tag=tag) def tagIds(s, tags, create=True): "Return an ID for all tags, creating if necessary." ids = {} if create: - s.statements("insert or ignore into tags (tag) values (:tag)", + s.statements("insert or ignore into tags (name) values (:tag)", [{'tag': t} for t in tags]) tagsD = dict([(x.lower(), y) for (x, y) in s.all(""" -select tag, id from tags -where tag in (%s)""" % ",".join([ +select name, id from tags +where name in (%s)""" % ",".join([ "'%s'" % t.replace("'", "''") for t in tags]))]) return tagsD diff --git a/anki/upgrade.py b/anki/upgrade.py index 8ef464f0e..7284caf3c 100644 --- a/anki/upgrade.py +++ b/anki/upgrade.py @@ -7,6 +7,15 @@ DECK_VERSION = 75 from anki.db import * from anki.lang import _ from anki.media import rebuildMediaDir +from anki.tags import initTagTables + +def moveTable(s, table): + sql = s.scalar( + "select sql from sqlite_master where name = '%s'" % table) + sql = sql.replace("TABLE "+table, "temporary table %s2" % table) + s.execute(sql) + s.execute("insert into %s2 select * from %s" % (table, table)) + s.execute("drop table "+table) def upgradeSchema(engine, s): "Alter tables prior to ORM initialization." @@ -20,22 +29,26 @@ def upgradeSchema(engine, s): except: pass if ver < 75: - # copy cards into new temporary table - sql = s.scalar( - "select sql from sqlite_master where name = 'cards'") - sql = sql.replace("TABLE cards", "temporary table cards2") - s.execute(sql) - s.execute("insert into cards2 select * from cards") - # drop the old cards table and create the new one - s.execute("drop table cards") + # migrate cards + moveTable(s, "cards") import cards metadata.create_all(engine, tables=[cards.cardsTable]) - # move data across and delete temp table + # move data across s.execute(""" insert into cards select id, factId, cardModelId, created, modified, question, answer, 0, ordinal, 0, relativeDelay, type, lastInterval, interval, due, factor, reps, successive, noCount from cards2""") s.execute("drop table cards2") + # migrate tags + moveTable(s, "tags") + moveTable(s, "cardTags") + initTagTables(s) + # move data across + s.execute("insert or ignore into tags select id, tag, 0 from tags2") + s.execute(""" +insert or ignore into cardTags select cardId, tagId, src from cardTags2""") + s.execute("drop table tags2") + s.execute("drop table cardTags2") return ver def updateIndices(deck): @@ -80,16 +93,6 @@ create index if not exists ix_factsDeleted_factId on factsDeleted (factId)""") deck.db.statement(""" create index if not exists ix_mediaDeleted_factId on mediaDeleted (mediaId)""") # tags - txt = "create unique index if not exists ix_tags_tag on tags (tag)" - try: - deck.db.statement(txt) - except: - deck.db.statement(""" -delete from tags where exists (select 1 from tags t2 where tags.tag = t2.tag -and tags.rowid > t2.rowid)""") - deck.db.statement(txt) - deck.db.statement(""" -create index if not exists ix_cardTags_tagCard on cardTags (tagId, cardId)""") deck.db.statement(""" create index if not exists ix_cardTags_cardId on cardTags (cardId)""")