Merge remote branch 'remotes/elrond/dev/init'
[mediagoblin.git] / mediagoblin / db / util.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011 Free Software Foundation, Inc
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 """
18 Utilities for database operations.
19
20 Some note on migration and indexing tools:
21
22 We store information about what the state of the database is in the
23 'mediagoblin' document of the 'app_metadata' collection. Keys in that
24 document relevant to here:
25
26 - 'migration_number': The integer representing the current state of
27 the migrations
28 """
29
30 import copy
31
32 # Imports that other modules might use
33 from pymongo import ASCENDING, DESCENDING
34 from pymongo.errors import InvalidId
35 from mongokit import ObjectId
36
37 from mediagoblin.db.indexes import ACTIVE_INDEXES, DEPRECATED_INDEXES
38
39
40 def add_new_indexes(database, active_indexes=ACTIVE_INDEXES):
41 """
42 Add any new indexes to the database.
43
44 Args:
45 - database: pymongo or mongokit database instance.
46 - active_indexes: indexes to possibly add in the pattern of:
47 {'collection_name': {
48 'identifier': {
49 'index': [index_foo_goes_here],
50 'unique': True}}
51 where 'index' is the index to add and all other options are
52 arguments for collection.create_index.
53
54 Returns:
55 A list of indexes added in form ('collection', 'index_name')
56 """
57 indexes_added = []
58
59 for collection_name, indexes in active_indexes.iteritems():
60 collection = database[collection_name]
61 collection_indexes = collection.index_information().keys()
62
63 for index_name, index_data in indexes.iteritems():
64 if not index_name in collection_indexes:
65 # Get a copy actually so we don't modify the actual
66 # structure
67 index_data = copy.copy(index_data)
68 index = index_data.pop('index')
69 collection.create_index(
70 index, name=index_name, **index_data)
71
72 indexes_added.append((collection_name, index_name))
73
74 return indexes_added
75
76
77 def remove_deprecated_indexes(database, deprecated_indexes=DEPRECATED_INDEXES):
78 """
79 Remove any deprecated indexes from the database.
80
81 Args:
82 - database: pymongo or mongokit database instance.
83 - deprecated_indexes: the indexes to deprecate in the pattern of:
84 {'collection_name': {
85 'identifier': {
86 'index': [index_foo_goes_here],
87 'unique': True}}
88
89 (... although we really only need the 'identifier' here, as the
90 rest of the information isn't used in this case. But it's kept
91 around so we can remember what it was)
92
93 Returns:
94 A list of indexes removed in form ('collection', 'index_name')
95 """
96 indexes_removed = []
97
98 for collection_name, indexes in deprecated_indexes.iteritems():
99 collection = database[collection_name]
100 collection_indexes = collection.index_information().keys()
101
102 for index_name, index_data in indexes.iteritems():
103 if index_name in collection_indexes:
104 collection.drop_index(index_name)
105
106 indexes_removed.append((collection_name, index_name))
107
108 return indexes_removed