refactor tags

- tags.tag -> tags.name
- priority reset to 0 for now; will be used differently in the future
- cardTags.id removed; (tagId, cardId) is the primary key now
- cardTags.src -> cardTags.type
This commit is contained in:
Damien Elmes 2011-02-22 03:16:12 +09:00
parent 1b9866b4e7
commit d9c0fba171
3 changed files with 45 additions and 47 deletions

View file

@ -1933,13 +1933,13 @@ and cards.factId = facts.id""")
tag = tag.replace("*", "%") tag = tag.replace("*", "%")
if "%" in tag: if "%" in tag:
ids = self.db.column0( 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: if search == "and" and not ids:
return [] return []
tagIds.append(ids) tagIds.append(ids)
else: else:
id = self.db.scalar( 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: if search == "and" and not id:
return [] return []
tagIds.append(id) tagIds.append(id)
@ -1962,7 +1962,7 @@ and cards.factId = facts.id""")
return self.db.column0(q) return self.db.column0(q)
def allTags(self): 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=""): def allTags_(self, where=""):
t = self.db.column0("select tags from facts %s" % where) t = self.db.column0("select tags from facts %s" % where)
@ -2034,7 +2034,7 @@ facts.modelId = :id""", id=modelId))
if d: if d:
self.db.statements(""" self.db.statements("""
insert into cardTags insert into cardTags
(cardId, tagId, src) values (cardId, tagId, type) values
(:cardId, :tagId, :src)""", d) (:cardId, :tagId, :src)""", d)
self.deleteUnusedTags() self.deleteUnusedTags()
@ -2527,7 +2527,7 @@ select cards.id from cards, facts where facts.tags = '' and cards.factId = facts
else: else:
token = token.replace("*", "%") token = token.replace("*", "%")
ids = self.db.column0(""" 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 += """ tquery += """
select cardId from cardTags where cardTags.tagId in %s""" % ids2str(ids) select cardId from cardTags where cardTags.tagId in %s""" % ids2str(ids)
elif type == SEARCH_TYPE: elif type == SEARCH_TYPE:
@ -2574,7 +2574,7 @@ select cardId from cardTags where cardTags.tagId in %s""" % ids2str(ids)
elif type == SEARCH_CARD: elif type == SEARCH_CARD:
token = token.replace("*", "%") token = token.replace("*", "%")
ids = self.db.column0(""" 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 isNeg:
if cmquery['neg']: if cmquery['neg']:
cmquery['neg'] += " intersect " cmquery['neg'] += " intersect "
@ -3108,7 +3108,7 @@ where id in %s""" % ids2str(ids)):
f['Answer'] = repl(a) f['Answer'] = repl(a)
try: try:
f.tags = self.db.scalar(""" 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"" where cardId = :cid and ct.tagId = t.id""", cid=id) or u""
except: except:
raise Exception("Your sqlite is too old.") raise Exception("Your sqlite is too old.")

View file

@ -4,51 +4,46 @@
from anki.db import * from anki.db import *
#src 0 = fact # Type: 0=fact, 1=model, 2=template
#src 1 = model # Priority: -100 to 100
#src 2 = card model
# Tables
##########################################################################
# priority is no longer used
# older sqlalchemy versions didn't support collate for sqlite, so we do it
# manually
def initTagTables(s): def initTagTables(s):
try: try:
s.statement(""" s.execute("""
create table tags ( create table tags (
id integer not null, id integer not null,
tag text not null collate nocase, name text not null collate nocase unique,
priority integer not null default 2, priority integer not null default 0,
primary key(id))""") primary key(id))""")
s.statement(""" s.execute("""
create table cardTags ( create table cardTags (
id integer not null,
cardId integer not null, cardId integer not null,
tagId integer not null, tagId integer not null,
src integer not null, type integer not null,
primary key(id))""") primary key(tagId, cardId))""")
except: except:
pass pass
def tagId(s, tag, create=True): def tagId(s, tag, create=True):
"Return ID for tag, creating if necessary." "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: if id or not create:
return id return id
s.statement(""" s.statement("""
insert or ignore into tags insert or ignore into tags
(tag) values (:tag)""", tag=tag) (name) values (:tag)""", tag=tag)
return s.scalar("select id from tags where tag = :tag", tag=tag) return s.scalar("select id from tags where name = :tag", tag=tag)
def tagIds(s, tags, create=True): def tagIds(s, tags, create=True):
"Return an ID for all tags, creating if necessary." "Return an ID for all tags, creating if necessary."
ids = {} ids = {}
if create: 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]) [{'tag': t} for t in tags])
tagsD = dict([(x.lower(), y) for (x, y) in s.all(""" tagsD = dict([(x.lower(), y) for (x, y) in s.all("""
select tag, id from tags select name, id from tags
where tag in (%s)""" % ",".join([ where name in (%s)""" % ",".join([
"'%s'" % t.replace("'", "''") for t in tags]))]) "'%s'" % t.replace("'", "''") for t in tags]))])
return tagsD return tagsD

View file

@ -7,6 +7,15 @@ DECK_VERSION = 75
from anki.db import * from anki.db import *
from anki.lang import _ from anki.lang import _
from anki.media import rebuildMediaDir 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): def upgradeSchema(engine, s):
"Alter tables prior to ORM initialization." "Alter tables prior to ORM initialization."
@ -20,22 +29,26 @@ def upgradeSchema(engine, s):
except: except:
pass pass
if ver < 75: if ver < 75:
# copy cards into new temporary table # migrate cards
sql = s.scalar( moveTable(s, "cards")
"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")
import cards import cards
metadata.create_all(engine, tables=[cards.cardsTable]) metadata.create_all(engine, tables=[cards.cardsTable])
# move data across and delete temp table # move data across
s.execute(""" s.execute("""
insert into cards select id, factId, cardModelId, created, modified, insert into cards select id, factId, cardModelId, created, modified,
question, answer, 0, ordinal, 0, relativeDelay, type, lastInterval, interval, question, answer, 0, ordinal, 0, relativeDelay, type, lastInterval, interval,
due, factor, reps, successive, noCount from cards2""") due, factor, reps, successive, noCount from cards2""")
s.execute("drop table 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 return ver
def updateIndices(deck): def updateIndices(deck):
@ -80,16 +93,6 @@ create index if not exists ix_factsDeleted_factId on factsDeleted (factId)""")
deck.db.statement(""" deck.db.statement("""
create index if not exists ix_mediaDeleted_factId on mediaDeleted (mediaId)""") create index if not exists ix_mediaDeleted_factId on mediaDeleted (mediaId)""")
# tags # 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(""" deck.db.statement("""
create index if not exists ix_cardTags_cardId on cardTags (cardId)""") create index if not exists ix_cardTags_cardId on cardTags (cardId)""")