1TABLE_TYPE = object()
2VIEW_TYPE = object()
3
4
5class NameMissingException(Exception):
6    pass
7
8
9def drop_views(manager, views):
10    """
11    Drops the specified views from the database
12
13    If a specified view does not exist in the database, this method fails
14    without modification
15
16    @param manager the migration manager
17    @param views the views to drop
18    """
19    check_exists(manager, views, VIEW_TYPE)
20    for view in views:
21        manager.execute('DROP VIEW `%s`' % view)
22
23
24def rename(manager, mapping):
25    """
26    Renames specified tables in the database
27
28    Use this to rename a specified set of tables in a database. If a source in
29    the mapping does not exist, this method fails without modification.
30
31    @param manager the migration manager
32    @param mapping a dictionary of orig_name => new_name. Any table not matching
33                   an entry in this dictionary will not be renamed
34    """
35    check_exists(manager, (table for table, _ in mapping.iteritems()),
36                  TABLE_TYPE)
37    for orig_name, new_name in mapping.iteritems():
38        manager.execute('RENAME TABLE `%s` TO `%s`' % (orig_name, new_name))
39
40
41def move_tables(manager, src_manager, tables):
42    """
43    Moves the specified tables from another database
44
45    If a table does not exist in the source database, this method fails without
46    modification
47
48    @param manager the migration manager
49    @param src_manager a migration manager that handles the source database
50    @param tables a list of tables to move
51    """
52    check_exists(src_manager, tables, TABLE_TYPE)
53    for table in tables:
54        manager.execute('RENAME TABLE `%(db)s`.`%(table)s` TO `%(table)s`'
55                        % dict(db=src_manager.get_db_name(), table=table))
56
57
58def drop_database(manager):
59    """
60    Drops the database that the specified manager controls
61
62    @param manager the migration manager
63    """
64    manager.execute('DROP DATABASE `%s`' % manager.get_db_name())
65
66
67def check_exists(manager, names, type):
68    """
69    Checks if the tables or views exists.
70
71    Raise an Exception if any of the names do not exist
72
73    @param manager the migration manager
74    @param names the table/view names
75    @param type one of 'TABLE' or 'VIEW'
76    """
77    if type == TABLE_TYPE:
78        info_table = 'TABLES'
79    elif type == VIEW_TYPE:
80        info_table = 'VIEWS'
81    else:
82        raise Exception("type parameter must be either TABLE_TYPE or VIEW_TYPE")
83
84    query = ('SELECT table_name FROM information_schema.%s '
85             'WHERE table_schema = %%s' % info_table)
86    rows = manager.execute(query, manager.get_db_name())
87    existing_names = [row[0] for row in rows]
88
89    for name in names:
90        if name not in existing_names:
91            raise NameMissingException(
92                    '%s missing from database, stopping' % name)
93
94
95def check_index_exists(manager, table_name, index_name):
96    """
97    Checks if a particular index exists on the table
98
99    @param manager the migration manager
100    @param table_name the table to check
101    @param index_name the index to check
102    """
103    query = ('SELECT 1 FROM information_schema.statistics '
104             'WHERE table_schema = %s AND table_name = %s AND index_name = %s')
105    rows = manager.execute(query, manager.get_db_name(), table_name, index_name)
106    return bool(rows)
107
108
109DJANGO_AUTH_TABLES = ('auth_group', 'auth_group_permissions', 'auth_permission')
110
111def auth_tables_exist(manager):
112    try:
113        check_exists(manager, DJANGO_AUTH_TABLES, TABLE_TYPE)
114        return True
115    except NameMissingException:
116        return False
117