diff --git a/anki/exporting.py b/anki/exporting.py
index 074a4a41e..8a9b6a516 100644
--- a/anki/exporting.py
+++ b/anki/exporting.py
@@ -122,7 +122,7 @@ select models.id, models.modified from models, facts where
facts.modelId = models.id and
facts.id in %s""" % ids2str([f[0] for f in facts]))
media = self.deck.db.all("""
-select id, created from media""")
+select id, modified from media""")
return {
# cards
"cards": cards,
diff --git a/anki/media.py b/anki/media.py
index e8e68afbf..31a3c9b68 100644
--- a/anki/media.py
+++ b/anki/media.py
@@ -17,22 +17,10 @@ regexps = ("(?i)(\[sound:([^]]+)\])",
mediaTable = Table(
'media', metadata,
Column('id', Integer, primary_key=True, nullable=False),
- Column('filename', UnicodeText, nullable=False),
- # reused as reference count
- Column('size', Integer, nullable=False),
- # treated as modification date, not creation date
- Column('created', Float, nullable=False),
- # reused as md5sum. empty string if file doesn't exist on disk
- Column('originalPath', UnicodeText, nullable=False, default=u""),
- # older versions stored original filename here, so we'll leave it for now
- # in case we add a feature to rename media back to its original name. in
- # the future we may want to zero this to save space
- Column('description', UnicodeText, nullable=False, default=u""))
-
-class Media(object):
- pass
-
-mapper(Media, mediaTable)
+ Column('filename', UnicodeText, nullable=False, unique=True),
+ Column('refcnt', Integer, nullable=False),
+ Column('modified', Float, nullable=False),
+ Column('chksum', UnicodeText, nullable=False, default=u""))
mediaDeletedTable = Table(
'mediaDeleted', metadata,
@@ -51,7 +39,7 @@ If a file with the same name exists, return a unique name.
This does not modify the media table."""
# see if have duplicate contents
newpath = deck.db.scalar(
- "select filename from media where originalPath = :cs",
+ "select filename from media where chksum = :cs",
cs=checksum(open(path, "rb").read()))
# check if this filename already exists
if not newpath:
@@ -88,7 +76,7 @@ def updateMediaCount(deck, file, count=1):
if deck.db.scalar(
"select 1 from media where filename = :file", file=file):
deck.db.statement(
- "update media set size = size + :c, created = :t where filename = :file",
+ "update media set refcnt = refcnt + :c, modified = :t where filename = :file",
file=file, c=count, t=time.time())
elif count > 0:
try:
@@ -97,17 +85,17 @@ def updateMediaCount(deck, file, count=1):
except:
sum = u""
deck.db.statement("""
-insert into media (id, filename, size, created, originalPath, description)
-values (:id, :file, :c, :mod, :sum, '')""",
+insert into media (id, filename, refcnt, modified, chksum)
+values (:id, :file, :c, :mod, :sum)""",
id=genID(), file=file, c=count, mod=time.time(),
sum=sum)
def removeUnusedMedia(deck):
- ids = deck.db.column0("select id from media where size = 0")
+ ids = deck.db.column0("select id from media where refcnt = 0")
for id in ids:
deck.db.statement("insert into mediaDeleted values (:id, :t)",
id=id, t=time.time())
- deck.db.statement("delete from media where size = 0")
+ deck.db.statement("delete from media where refcnt = 0")
# String manipulation
##########################################################################
@@ -147,7 +135,7 @@ def rebuildMediaDir(deck, delete=False, dirty=True):
return (0, 0)
deck.startProgress(title=_("Check Media DB"))
# set all ref counts to 0
- deck.db.statement("update media set size = 0")
+ deck.db.statement("update media set refcnt = 0")
# look through cards for media references
refs = {}
normrefs = {}
@@ -186,8 +174,8 @@ def rebuildMediaDir(deck, delete=False, dirty=True):
removeUnusedMedia(deck)
# check md5s are up to date
update = []
- for (file, created, md5) in deck.db.all(
- "select filename, created, originalPath from media"):
+ for (file, md5) in deck.db.all(
+ "select filename, chksum from media"):
path = os.path.join(mdir, file)
if not os.path.exists(path):
if md5:
@@ -199,12 +187,12 @@ def rebuildMediaDir(deck, delete=False, dirty=True):
update.append({'f':file, 'sum':sum, 'c':time.time()})
if update:
deck.db.statements("""
-update media set originalPath = :sum, created = :c where filename = :f""",
+update media set chksum = :sum, modified = :c where filename = :f""",
update)
# update deck and get return info
if dirty:
deck.flushMod()
- nohave = deck.db.column0("select filename from media where originalPath = ''")
+ nohave = deck.db.column0("select filename from media where chksum = ''")
deck.finishProgress()
return (nohave, unused)
@@ -220,7 +208,7 @@ def downloadMissing(deck):
missing = 0
grabbed = 0
for c, (f, sum) in enumerate(deck.db.all(
- "select filename, originalPath from media")):
+ "select filename, chksum from media")):
path = os.path.join(mdir, f)
if not os.path.exists(path):
try:
diff --git a/anki/upgrade.py b/anki/upgrade.py
index 49eadadae..dd02597ac 100644
--- a/anki/upgrade.py
+++ b/anki/upgrade.py
@@ -29,35 +29,45 @@ def upgradeSchema(engine, s):
except:
pass
if ver < 75:
- # migrate cards
+ # cards
+ ###########
moveTable(s, "cards")
import cards
metadata.create_all(engine, tables=[cards.cardsTable])
- # 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
+ # 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")
- # migrate facts
+ # facts
+ ###########
moveTable(s, "facts")
import facts
metadata.create_all(engine, tables=[facts.factsTable])
- # move data across
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):
@@ -84,14 +94,10 @@ create index if not exists ix_cards_factId on cards (factId)""")
deck.db.statement("""
create index if not exists ix_fields_factId on fields (factId)""")
deck.db.statement("""
-create index if not exists ix_fields_fieldModelId on fields (fieldModelId)""")
- deck.db.statement("""
create index if not exists ix_fields_chksum on fields (chksum)""")
# media
deck.db.statement("""
-create unique index if not exists ix_media_filename on media (filename)""")
- deck.db.statement("""
-create index if not exists ix_media_originalPath on media (originalPath)""")
+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)""")
@@ -173,6 +179,8 @@ cast(min(thinkingTime, 60)*1000 as int), 0 from reviewHistory""")
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
diff --git a/tests/test_media.py b/tests/test_media.py
index 10c8a9c5c..c406ee3f2 100644
--- a/tests/test_media.py
+++ b/tests/test_media.py
@@ -34,7 +34,7 @@ def test_copy():
assert m.copyToMedia(deck, path) == "foo.jpg"
# dupe md5
deck.db.statement("""
-insert into media values (null, 'foo.jpg', 0, 0, :sum, '')""",
+insert into media values (null, 'foo.jpg', 0, 0, :sum)""",
sum=checksum("hello"))
path = os.path.join(dir, "bar.jpg")
open(path, "w").write("hello")
@@ -54,53 +54,53 @@ def test_db():
deck.addFact(f)
# 1 entry in the media db, with two references, and missing file
assert deck.db.scalar("select count() from media") == 1
- assert deck.db.scalar("select size from media") == 2
- assert deck.db.scalar("select not originalPath from media")
+ assert deck.db.scalar("select refcnt from media") == 2
+ assert not deck.db.scalar("select group_concat(chksum, '') from media")
# copy to media folder & check db
path = m.copyToMedia(deck, path)
m.rebuildMediaDir(deck)
# md5 should be set now
assert deck.db.scalar("select count() from media") == 1
- assert deck.db.scalar("select size from media") == 2
- assert deck.db.scalar("select originalPath from media")
+ assert deck.db.scalar("select refcnt from media") == 2
+ assert deck.db.scalar("select group_concat(chksum, '') from media")
# edit the fact to remove a reference
f['Back'] = u""
f.setModified(True, deck)
deck.db.flush()
assert deck.db.scalar("select count() from media") == 1
- assert deck.db.scalar("select size from media") == 1
+ assert deck.db.scalar("select refcnt from media") == 1
# remove the front reference too
f['Front'] = u""
f.setModified(True, deck)
- assert deck.db.scalar("select size from media") == 0
+ assert deck.db.scalar("select refcnt from media") == 0
# add the reference back
f['Front'] = u"
"
f.setModified(True, deck)
- assert deck.db.scalar("select size from media") == 1
+ assert deck.db.scalar("select refcnt from media") == 1
# detect file modifications
- oldsum = deck.db.scalar("select originalPath from media")
+ oldsum = deck.db.scalar("select chksum from media")
open(path, "w").write("world")
m.rebuildMediaDir(deck)
- newsum = deck.db.scalar("select originalPath from media")
+ newsum = deck.db.scalar("select chksum from media")
assert newsum and newsum != oldsum
# delete underlying file and check db
os.unlink(path)
m.rebuildMediaDir(deck)
# md5 should be gone again
assert deck.db.scalar("select count() from media") == 1
- assert deck.db.scalar("select not originalPath from media")
+ assert deck.db.scalar("select not chksum from media")
# media db should pick up media defined via templates & bulk update
f['Back'] = u"bar.jpg"
f.setModified(True, deck)
deck.db.flush()
# modify template & regenerate
assert deck.db.scalar("select count() from media") == 1
- assert deck.db.scalar("select sum(size) from media") == 1
+ assert deck.db.scalar("select sum(refcnt) from media") == 1
deck.currentModel.cardModels[0].aformat=u'
'
deck.updateCardsFromModel(deck.currentModel)
- assert deck.db.scalar("select sum(size) from media") == 2
+ assert deck.db.scalar("select sum(refcnt) from media") == 2
assert deck.db.scalar("select count() from media") == 2
deck.currentModel.cardModels[0].aformat=u'{{{Back}}}'
deck.updateCardsFromModel(deck.currentModel)
assert deck.db.scalar("select count() from media") == 2
- assert deck.db.scalar("select sum(size) from media") == 1
+ assert deck.db.scalar("select sum(refcnt) from media") == 1