~ubuntu-branches/debian/sid/calibre/sid

« back to all changes in this revision

Viewing changes to src/calibre/db/schema_upgrades.py

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2014-05-14 18:17:50 UTC
  • mto: This revision was merged to the branch mainline in revision 75.
  • Revision ID: package-import@ubuntu.com-20140514181750-efj1wymey2vb4cao
Tags: upstream-1.36.0+dfsg
ImportĀ upstreamĀ versionĀ 1.36.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 
15
15
class SchemaUpgrade(object):
16
16
 
17
 
    def __init__(self, conn, library_path, field_metadata):
18
 
        conn.execute('BEGIN EXCLUSIVE TRANSACTION')
19
 
        self.conn = conn
 
17
    def __init__(self, db, library_path, field_metadata):
 
18
        db.execute('BEGIN EXCLUSIVE TRANSACTION')
 
19
        self.db = db
20
20
        self.library_path = library_path
21
21
        self.field_metadata = field_metadata
22
22
        # Upgrade database
23
23
        try:
24
24
            while True:
25
 
                uv = self.conn.execute('pragma user_version').next()[0]
 
25
                uv = self.db.execute('pragma user_version').next()[0]
26
26
                meth = getattr(self, 'upgrade_version_%d'%uv, None)
27
27
                if meth is None:
28
28
                    break
29
29
                else:
30
30
                    prints('Upgrading database to version %d...'%(uv+1))
31
31
                    meth()
32
 
                    self.conn.execute('pragma user_version=%d'%(uv+1))
 
32
                    self.db.execute('pragma user_version=%d'%(uv+1))
33
33
        except:
34
 
            self.conn.execute('ROLLBACK')
 
34
            self.db.execute('ROLLBACK')
35
35
            raise
36
36
        else:
37
 
            self.conn.execute('COMMIT')
 
37
            self.db.execute('COMMIT')
38
38
        finally:
39
 
            self.conn = self.field_metadata = None
 
39
            self.db = self.field_metadata = None
40
40
 
41
41
    def upgrade_version_1(self):
42
42
        '''
43
43
        Normalize indices.
44
44
        '''
45
 
        self.conn.execute('''\
 
45
        self.db.execute('''\
46
46
        DROP INDEX IF EXISTS authors_idx;
47
47
        CREATE INDEX authors_idx ON books (author_sort COLLATE NOCASE, sort COLLATE NOCASE);
48
48
        DROP INDEX IF EXISTS series_idx;
65
65
        END;
66
66
        DELETE FROM %(table)s WHERE (SELECT COUNT(id) FROM books_%(ltable)s_link WHERE %(ltable_col)s=%(table)s.id) < 1;
67
67
        '''
68
 
        self.conn.execute(script%dict(ltable='authors', table='authors', ltable_col='author'))
69
 
        self.conn.execute(script%dict(ltable='publishers', table='publishers', ltable_col='publisher'))
70
 
        self.conn.execute(script%dict(ltable='tags', table='tags', ltable_col='tag'))
71
 
        self.conn.execute(script%dict(ltable='series', table='series', ltable_col='series'))
 
68
        self.db.execute(script%dict(ltable='authors', table='authors', ltable_col='author'))
 
69
        self.db.execute(script%dict(ltable='publishers', table='publishers', ltable_col='publisher'))
 
70
        self.db.execute(script%dict(ltable='tags', table='tags', ltable_col='tag'))
 
71
        self.db.execute(script%dict(ltable='series', table='series', ltable_col='series'))
72
72
 
73
73
    def upgrade_version_3(self):
74
74
        ' Add path to result cache '
75
 
        self.conn.execute('''
 
75
        self.db.execute('''
76
76
        DROP VIEW IF EXISTS meta;
77
77
        CREATE VIEW meta AS
78
78
        SELECT id, title,
95
95
 
96
96
    def upgrade_version_4(self):
97
97
        'Rationalize books table'
98
 
        self.conn.execute('''
 
98
        self.db.execute('''
99
99
        CREATE TEMPORARY TABLE
100
100
        books_backup(id,title,sort,timestamp,series_index,author_sort,isbn,path);
101
101
        INSERT INTO books_backup SELECT id,title,sort,timestamp,series_index,author_sort,isbn,path FROM books;
142
142
 
143
143
    def upgrade_version_5(self):
144
144
        'Update indexes/triggers for new books table'
145
 
        self.conn.execute('''
 
145
        self.db.execute('''
146
146
        CREATE INDEX authors_idx ON books (author_sort COLLATE NOCASE);
147
147
        CREATE INDEX books_idx ON books (sort COLLATE NOCASE);
148
148
        CREATE TRIGGER books_delete_trg
174
174
 
175
175
    def upgrade_version_6(self):
176
176
        'Show authors in order'
177
 
        self.conn.execute('''
 
177
        self.db.execute('''
178
178
        DROP VIEW IF EXISTS meta;
179
179
        CREATE VIEW meta AS
180
180
        SELECT id, title,
200
200
 
201
201
    def upgrade_version_7(self):
202
202
        'Add uuid column'
203
 
        self.conn.execute('''
 
203
        self.db.execute('''
204
204
        ALTER TABLE books ADD COLUMN uuid TEXT;
205
205
        DROP TRIGGER IF EXISTS books_insert_trg;
206
206
        DROP TRIGGER IF EXISTS books_update_trg;
243
243
    def upgrade_version_8(self):
244
244
        'Add Tag Browser views'
245
245
        def create_tag_browser_view(table_name, column_name):
246
 
            self.conn.execute('''
 
246
            self.db.execute('''
247
247
                DROP VIEW IF EXISTS tag_browser_{tn};
248
248
                CREATE VIEW tag_browser_{tn} AS SELECT
249
249
                    id,
260
260
 
261
261
    def upgrade_version_9(self):
262
262
        'Add custom columns'
263
 
        self.conn.execute('''
 
263
        self.db.execute('''
264
264
                CREATE TABLE custom_columns (
265
265
                    id       INTEGER PRIMARY KEY AUTOINCREMENT,
266
266
                    label    TEXT NOT NULL,
295
295
                        {cn}={tn}.id AND books_list_filter(book)) count
296
296
                FROM {tn};
297
297
                '''.format(tn=table_name, cn=column_name, vcn=view_column_name))
298
 
            self.conn.execute(script)
 
298
            self.db.execute(script)
299
299
 
300
300
        for field in self.field_metadata.itervalues():
301
301
            if field['is_category'] and not field['is_custom'] and 'link_column' in field:
302
 
                table = self.conn.get(
 
302
                table = self.db.get(
303
303
                    'SELECT name FROM sqlite_master WHERE type="table" AND name=?',
304
304
                    ('books_%s_link'%field['table'],), all=False)
305
305
                if table is not None:
337
337
 
338
338
                '''.format(tn=table_name, cn=column_name,
339
339
                           vcn=view_column_name, scn=sort_column_name))
340
 
            self.conn.execute(script)
 
340
            self.db.execute(script)
341
341
 
342
342
        def create_cust_tag_browser_view(table_name, link_table_name):
343
343
            script = '''
371
371
                     value AS sort
372
372
                FROM {table};
373
373
                '''.format(lt=link_table_name, table=table_name)
374
 
            self.conn.execute(script)
 
374
            self.db.execute(script)
375
375
 
376
376
        for field in self.field_metadata.itervalues():
377
377
            if field['is_category'] and not field['is_custom'] and 'link_column' in field:
378
 
                table = self.conn.get(
 
378
                table = self.db.get(
379
379
                    'SELECT name FROM sqlite_master WHERE type="table" AND name=?',
380
380
                    ('books_%s_link'%field['table'],), all=False)
381
381
                if table is not None:
382
382
                    create_std_tag_browser_view(field['table'], field['link_column'],
383
383
                                            field['column'], field['category_sort'])
384
384
 
385
 
        db_tables = self.conn.get('''SELECT name FROM sqlite_master
 
385
        db_tables = self.db.get('''SELECT name FROM sqlite_master
386
386
                                     WHERE type='table'
387
387
                                     ORDER BY name''')
388
388
        tables = []
393
393
            if table.startswith('custom_column_') and link_table in tables:
394
394
                create_cust_tag_browser_view(table, link_table)
395
395
 
396
 
        self.conn.execute('UPDATE authors SET sort=author_to_author_sort(name)')
 
396
        self.db.execute('UPDATE authors SET sort=author_to_author_sort(name)')
397
397
 
398
398
    def upgrade_version_12(self):
399
399
        'DB based preference store'
404
404
                                 val TEXT NON NULL,
405
405
                                 UNIQUE(key));
406
406
        '''
407
 
        self.conn.execute(script)
 
407
        self.db.execute(script)
408
408
 
409
409
    def upgrade_version_13(self):
410
410
        'Dirtied table for OPF metadata backups'
415
415
                             UNIQUE(book));
416
416
        INSERT INTO metadata_dirtied (book) SELECT id FROM books;
417
417
        '''
418
 
        self.conn.execute(script)
 
418
        self.db.execute(script)
419
419
 
420
420
    def upgrade_version_14(self):
421
421
        'Cache has_cover'
422
 
        self.conn.execute('ALTER TABLE books ADD COLUMN has_cover BOOL DEFAULT 0')
423
 
        data = self.conn.get('SELECT id,path FROM books', all=True)
 
422
        self.db.execute('ALTER TABLE books ADD COLUMN has_cover BOOL DEFAULT 0')
 
423
        data = self.db.get('SELECT id,path FROM books', all=True)
424
424
        def has_cover(path):
425
425
            if path:
426
426
                path = os.path.join(self.library_path, path.replace('/', os.sep),
429
429
            return False
430
430
 
431
431
        ids = [(x[0],) for x in data if has_cover(x[1])]
432
 
        self.conn.executemany('UPDATE books SET has_cover=1 WHERE id=?', ids)
 
432
        self.db.executemany('UPDATE books SET has_cover=1 WHERE id=?', ids)
433
433
 
434
434
    def upgrade_version_15(self):
435
435
        'Remove commas from tags'
436
 
        self.conn.execute("UPDATE OR IGNORE tags SET name=REPLACE(name, ',', ';')")
437
 
        self.conn.execute("UPDATE OR IGNORE tags SET name=REPLACE(name, ',', ';;')")
438
 
        self.conn.execute("UPDATE OR IGNORE tags SET name=REPLACE(name, ',', '')")
 
436
        self.db.execute("UPDATE OR IGNORE tags SET name=REPLACE(name, ',', ';')")
 
437
        self.db.execute("UPDATE OR IGNORE tags SET name=REPLACE(name, ',', ';;')")
 
438
        self.db.execute("UPDATE OR IGNORE tags SET name=REPLACE(name, ',', '')")
439
439
 
440
440
    def upgrade_version_16(self):
441
 
        self.conn.execute('''
 
441
        self.db.execute('''
442
442
        DROP TRIGGER IF EXISTS books_update_trg;
443
443
        CREATE TRIGGER books_update_trg
444
444
            AFTER UPDATE ON books
472
472
                DELETE FROM books_plugin_data WHERE book=OLD.id;
473
473
        END;
474
474
        '''
475
 
        self.conn.execute(script)
 
475
        self.db.execute(script)
476
476
 
477
477
    def upgrade_version_18(self):
478
478
        '''
584
584
        '''%isoformat(DEFAULT_DATE, sep=' ')
585
585
        # Sqlite does not support non constant default values in alter
586
586
        # statements
587
 
        self.conn.execute(script)
 
587
        self.db.execute(script)
588
588
 
589
589
    def upgrade_version_19(self):
590
 
        recipes = self.conn.get('SELECT id,title,script FROM feeds')
 
590
        recipes = self.db.get('SELECT id,title,script FROM feeds')
591
591
        if recipes:
592
592
            from calibre.web.feeds.recipes import (custom_recipes,
593
593
                    custom_recipe_filename)
612
612
        script = '''
613
613
        ALTER TABLE authors ADD COLUMN link TEXT NOT NULL DEFAULT "";
614
614
        '''
615
 
        self.conn.execute(script)
 
615
        self.db.execute(script)
616
616
 
617
617