Ticket #3290: formdb.py

File formdb.py, 11.2 kB (added by anderson@ultraserver.com.br, 6 months ago)

The creation SQL scripts of this file were modified to work witk MySQL databases.

Line 
1 from trac.core import Component, implements
2 from tracdb import DBComponent
3 from iface import TracFormDBObserver
4 import unittest, time, cgi
5
6 class TracFormDBComponent(DBComponent):
7     applySchema = True
8     implements(TracFormDBObserver)
9
10     ###########################################################################
11     #
12     #   Form update methods.
13     #
14     ###########################################################################
15     def get_tracform_meta(self, src, cursor=None):
16         """
17         Returns the meta information about a form based on a form_id (int or
18         long) or context (string or unicode).
19         """
20         cursor = self.get_cursor(cursor)
21         sql = """
22             SELECT  tracform_id,
23                     context,
24                     updater,
25                     updated_on,
26                     keep_history,
27                     track_fields
28             FROM    tracform_forms
29             """
30         if isinstance(src, basestring):
31             sql += """
32                 WHERE   context = %s
33                 """
34         else:
35             sql += """
36                 WHERE   tracform_id = %s
37                 """
38         form_id = None
39         context = None
40         if isinstance(src, basestring):
41             context = src
42         else:
43             form_id = src
44         return (cursor(sql, src).firstrow or
45                 (form_id, context, None, None, None, None))
46
47     def get_tracform_state(self, src, cursor=None):
48         cursor = self.get_cursor(cursor)
49         sql = """
50             SELECT  state
51             FROM    tracform_forms
52             """
53         if isinstance(src, basestring):
54             sql += """
55                 WHERE   context = %s
56                 """
57         else:
58             sql += """
59                 WHERE   tracform_id = %s
60                 """
61         return cursor(sql, src).value
62
63     def save_tracform(self, src, state, updater,
64                         base_version=None, keep_history=False,
65                         track_fields=False, cursor=None):
66         cursor = self.get_cursor(cursor)
67         (form_id, context, last_updater, last_updated_on,
68             form_keep_history, form_track_fields) = self.get_tracform_meta(src)
69
70         if form_keep_history is not None:
71             keep_history = form_keep_history
72         old_state = self.get_tracform_state(src)
73         if form_track_fields is not None:
74             track_fields = form_track_fields
75
76         if base_version is not None:
77             base_version = int(base_version or 0)
78
79         if ((base_version is None and last_updated_on is None) or
80             (base_version == last_updated_on)):
81             if state != old_state:
82                 updated_on = int(time.time())
83                 if form_id is None:
84                     form_id = cursor("""
85                         INSERT INTO tracform_forms
86                             (context, state, updater, updated_on)
87                             VALUES (%s, %s, %s, %s)
88                         """, context, state, updater, updated_on).last_id
89                 else:
90                     cursor("""
91                         UPDATE  tracform_forms
92                         SET     state = %s,
93                                 updater = %s,
94                                 updated_on = %s
95                         WHERE   tracform_id = %s
96                         """, state, updater, updated_on, form_id)
97                     if keep_history:
98                         cursor("""
99                             INSERT INTO tracform_history
100                                     (tracform_id, updated_on,
101                                     updater, old_states)
102                                     VALUES (%s, %s, %s, %s)
103                             """, form_id, last_updated_on,
104                                 last_updater, old_state)
105                 if track_fields:
106                     # Break down old version and new version.
107                     old_fields = cgi.parse_qs(old_state or '')
108                     new_fields = cgi.parse_qs(state or '')
109                     updated_fields = []
110                     for field, old_value in old_fields.iteritems():
111                         if new_fields.get(field) != old_value:
112                             updated_fields.append(field)
113                     for field in new_fields:
114                         if old_fields.get(field) is None:
115                             updated_fields.append(field)
116                     self.log.debug('UPDATED: ' + str(updated_fields))
117                     for field in updated_fields:
118                         if cursor("""
119                             SELECT  COUNT(*)
120                             FROM    tracform_fields
121                             WHERE   tracform_id = %s
122                                 AND field = %s""", form_id, field).value:
123
124                             cursor("""
125                                 UPDATE  tracform_fields
126                                     SET updater = %s,
127                                         updated_on = %s
128                                 WHERE   tracform_id = %s
129                                     AND field = %s
130                                 """, updater, updated_on, form_id, field)
131                         else:
132                             cursor("""
133                                 INSERT INTO tracform_fields
134                                         (tracform_id, field,
135                                         updater, updated_on)
136                                 VALUES  (%s, %s, %s, %s)
137                                 """, form_id, field, updater, updated_on)
138             else:
139                 updated_on = last_updated_on
140                 updater = last_updater
141             return ((form_id, context, state, updater, updated_on),
142                     (form_id, context, old_state,
143                     last_updater, last_updated_on))
144         else:
145             raise ValueError("Conflict")
146
147     def get_tracform_history(self, src, cursor=None):
148         cursor = self.get_cursor(cursor)
149         form_id = self.get_tracform_meta(src, cursor=cursor)[0]
150         return cursor("""
151             SELECT  updater, updated_on, old_states
152             FROM    tracform_history
153             WHERE   tracform_id = %s
154             ORDER   BY updated_on DESC
155             """, form_id)
156
157     def get_tracform_fields(self, src, cursor=None):
158         cursor = self.get_cursor(cursor)
159         form_id = self.get_tracform_meta(src, cursor=cursor)[0]
160         return cursor("""
161             SELECT  field, updater, updated_on
162             FROM    tracform_fields
163             WHERE   tracform_id = %s
164             """, form_id)
165
166     def get_tracform_fieldinfo(self, src, field, cursor=None):
167         cursor = self.get_cursor(cursor)
168         form_id = self.get_tracform_meta(src, cursor=cursor)[0]
169         return cursor("""
170             SELECT  updater, updated_on
171             FROM    tracform_fields
172             WHERE   tracform_id = %s
173                 AND field = %s
174             """, form_id, field).firstrow or (None, None)
175
176     ###########################################################################
177     #
178     #   Schema components
179     #
180     ###########################################################################
181     def dbschema_2008_06_14_0000(self, cursor):
182         """
183         This was a simple test for the schema base class.
184         """
185
186     def dbschema_2008_06_15_0000(self, cursor):
187         "Create the major tables."
188         cursor("""
189             CREATE TABLE tracform_forms(
190                 tracform_id     int(10) unsigned NOT NULL auto_increment,
191                 context         varchar(100) NOT NULL,
192                 state           TEXT NOT NULL,
193                 updater         varchar(50) NOT NULL,
194                 updated_on      INTEGER NOT NULL,
195                   PRIMARY KEY  (`tracform_id`)
196                 )
197             """)
198         cursor("""
199             CREATE TABLE tracform_history(
200                 tracform_id     INTEGER NOT NULL,
201                 updated_on      INTEGER NOT NULL,
202                 updater         varchar(50) NOT NULL,
203                 old_states      TEXT NOT NULL
204                 );
205             """)
206
207     def dbschema_2008_06_15_0001(self, cursor):
208         "Create indices for tracform_forms table."
209         cursor("""
210             CREATE INDEX tracform_forms_context
211                 ON tracform_forms(context)
212             """)
213         cursor("""
214             CREATE INDEX tracform_forms_updater
215                 ON tracform_forms(updater)
216             """)
217         cursor("""
218             CREATE INDEX tracform_forms_updated_on
219                 ON tracform_forms(updated_on)
220             """)
221
222     def dbschema_2008_06_14_0002(self, cursor):
223         """
224         This was a modify table, but instead removed the data altogether.
225         """
226
227     def dbschema_2008_06_15_0003(self, cursor):
228         "Create indices for tracform_history table."
229         cursor("""
230             CREATE INDEX tracform_history_tracform_id
231                 ON tracform_history(tracform_id)
232             """)
233         cursor("""
234             CREATE INDEX tracform_history_updated_on
235                 ON tracform_history(updated_on DESC)
236             """)
237         cursor("""
238             CREATE INDEX tracform_history_updater
239                 ON tracform_history(updater)
240             """)
241
242     def dbschema_2008_06_15_0004(self, cursor):
243         "Recreating updated_on index for tracform_forms to be descending."
244         cursor("""
245             ALTER TABLE tracform_forms DROP INDEX tracform_forms_updated_on
246             """)
247         cursor("""
248             CREATE INDEX tracform_froms_updated_on
249                 ON tracform_forms(updated_on DESC)
250             """)
251
252     def dbschema_2008_06_15_0010(self, cursor):
253         "Also maintain whether history should me maintained for form."
254         cursor("""
255             ALTER TABLE tracform_forms
256                 ADD keep_history INTEGER
257             """)
258
259     def dbschema_2008_06_15_0011(self, cursor):
260         "Make the context a unique index."
261         cursor("""
262             ALTER TABLE tracform_forms DROP INDEX tracform_forms_context
263             """)
264         cursor("""
265             CREATE UNIQUE INDEX tracform_forms_context
266                 ON tracform_forms(context)
267             """)
268
269     def dbschema_2008_06_15_0012(self, cursor):
270         "Track who changes individual fields"
271         cursor("""
272             ALTER TABLE tracform_forms
273                 ADD track_fields INTEGER
274             """)
275         cursor("""
276             CREATE TABLE tracform_fields(
277                 tracform_id     INTEGER NOT NULL,
278                 field           varchar(100) NOT NULL,
279                 updater         TEXT NOT NULL,
280                 updated_on      INTEGER NOT NULL
281                 )
282             """)
283         cursor("""
284             CREATE UNIQUE INDEX tracform_fields_tracform_id_field
285                 ON tracform_fields(tracform_id, field)
286             """)
287
288 if __name__ == '__main__':
289     from trac.test import EnvironmentStub
290     env = EnvironmentStub()
291     db = TracFormDBComponent(env)
292     db.upgrade_environment(None)
293     updated_on_1 = db.save_tracform('/', 'hello world', 'me')[0][4]
294     assert db.get_tracform_state('/') == 'hello world'
295     updated_on_2 = \
296         db.save_tracform('/', 'ack oop', 'you', updated_on_1)[0][4]
297     assert db.get_tracform_state('/') == 'ack oop'
298     assert tuple(db.get_tracform_history('/')) == (
299         ('me', updated_on_1, 'hello world'),
300         )