Anki/anki/upgrade.py
Damien Elmes 2d1d946504 refactor media
- created->modified
- size->refcnt
- originalPath->chksum
- remove description
2011-04-28 09:23:28 +09:00

200 lines
7.3 KiB
Python

# -*- coding: utf-8 -*-
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
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."
ver = s.scalar("select version from decks limit 1")
# add a checksum to fields
if ver < 71:
try:
s.execute(
"alter table fields add column chksum text "+
"not null default ''")
except:
pass
if ver < 75:
# cards
###########
moveTable(s, "cards")
import cards
metadata.create_all(engine, tables=[cards.cardsTable])
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")
# tags
###########
moveTable(s, "tags")
moveTable(s, "cardTags")
initTagTables(s)
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")
# facts
###########
moveTable(s, "facts")
import facts
metadata.create_all(engine, tables=[facts.factsTable])
s.execute("""
insert or ignore into facts select id, modelId, created, modified, tags,
spaceUntil from facts2""")
s.execute("drop table facts2")
# media
###########
moveTable(s, "media")
import media
metadata.create_all(engine, tables=[media.mediaTable])
s.execute("""
insert or ignore into media select id, filename, size, created,
originalPath from media2""")
s.execute("drop table media2")
return ver
def updateIndices(deck):
"Add indices to the DB."
# due counts, failed card queue
deck.db.statement("""
create index if not exists ix_cards_queueDue on cards
(queue, due, factId)""")
# counting cards of a given type
deck.db.statement("""
create index if not exists ix_cards_type on cards
(type)""")
# sync summaries
deck.db.statement("""
create index if not exists ix_cards_modified on cards
(modified)""")
deck.db.statement("""
create index if not exists ix_facts_modified on facts
(modified)""")
# card spacing
deck.db.statement("""
create index if not exists ix_cards_factId on cards (factId)""")
# fields
deck.db.statement("""
create index if not exists ix_fields_factId on fields (factId)""")
deck.db.statement("""
create index if not exists ix_fields_chksum on fields (chksum)""")
# media
deck.db.statement("""
create index if not exists ix_media_chksum on media (chksum)""")
# deletion tracking
deck.db.statement("""
create index if not exists ix_cardsDeleted_cardId on cardsDeleted (cardId)""")
deck.db.statement("""
create index if not exists ix_modelsDeleted_modelId on modelsDeleted (modelId)""")
deck.db.statement("""
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
deck.db.statement("""
create index if not exists ix_cardTags_cardId on cardTags (cardId)""")
def upgradeDeck(deck):
"Upgrade deck to the latest version."
if deck.version < DECK_VERSION:
prog = True
deck.startProgress()
deck.updateProgress(_("Upgrading Deck..."))
if deck.utcOffset == -1:
# we're opening a shared deck with no indices - we'll need
# them if we want to rebuild the queue
updateIndices(deck)
oldmod = deck.modified
else:
prog = False
if deck.version < 65:
raise Exception("oldDeckVersion")
# skip a few to allow for updates to stable tree
if deck.version < 70:
# update dynamic indices given we don't use priority anymore
for d in ("intervalDesc", "intervalAsc", "randomOrder",
"dueAsc", "dueDesc"):
deck.db.statement("drop index if exists ix_cards_%s2" % d)
deck.db.statement("drop index if exists ix_cards_%s" % d)
deck.updateDynamicIndices()
# remove old views
for v in ("failedCards", "revCardsOld", "revCardsNew",
"revCardsDue", "revCardsRandom", "acqCardsRandom",
"acqCardsOld", "acqCardsNew"):
deck.db.statement("drop view if exists %s" % v)
deck.version = 70
deck.db.commit()
if deck.version < 71:
# remove the expensive value cache
deck.db.statement("drop index if exists ix_fields_value")
# add checksums and index
deck.updateAllFieldChecksums()
updateIndices(deck)
deck.db.execute("vacuum")
deck.db.execute("analyze")
deck.version = 71
deck.db.commit()
if deck.version < 72:
# this was only used for calculating average factor
deck.db.statement("drop index if exists ix_cards_factor")
deck.version = 72
deck.db.commit()
if deck.version < 73:
# remove stats, as it's all in the revlog now
deck.db.statement("drop table if exists stats")
deck.version = 73
deck.db.commit()
if deck.version < 74:
# migrate revlog data to new table
deck.db.statement("""
insert or ignore into revlog select
cast(time*1000 as int), cardId, ease, reps, lastInterval, nextInterval, nextFactor,
cast(min(thinkingTime, 60)*1000 as int), 0 from reviewHistory""")
deck.db.statement("drop table reviewHistory")
# convert old ease0 into ease1
deck.db.statement("update revlog set ease = 1 where ease = 0")
# remove priority index
deck.db.statement("drop index if exists ix_cards_priority")
deck.version = 74
deck.db.commit()
if deck.version < 75:
# suspended cards don't use ranges anymore
deck.db.execute("update cards set queue=-1 where queue between -3 and -1")
deck.db.execute("update cards set queue=-2 where queue between 3 and 5")
deck.db.execute("update cards set queue=-3 where queue between 6 and 8")
# don't need an index on fieldModelId
deck.db.statement("drop index if exists ix_fields_fieldModelId")
# new indices for new cards table
updateIndices(deck)
deck.version = 75
deck.db.commit()
# executing a pragma here is very slow on large decks, so we store
# our own record
if not deck.getInt("pageSize") == 4096:
deck.db.commit()
deck.db.execute("pragma page_size = 4096")
deck.db.execute("pragma legacy_file_format = 0")
deck.db.execute("vacuum")
deck.setVar("pageSize", 4096, mod=False)
deck.db.commit()
if prog:
assert deck.modified == oldmod
deck.finishProgress()