Merge lp:~wgrant/launchpad/pofile-filter-stormify into lp:launchpad
- pofile-filter-stormify
- Merge into devel
Proposed by
William Grant
Status: | Merged |
---|---|
Merged at revision: | 17369 |
Proposed branch: | lp:~wgrant/launchpad/pofile-filter-stormify |
Merge into: | lp:launchpad |
Diff against target: |
357 lines (+126/-141) 1 file modified
lib/lp/translations/model/pofile.py (+126/-141) |
To merge this branch: | bzr merge lp:~wgrant/launchpad/pofile-filter-stormify |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | code | Approve | |
Review via email: mp+251249@code.launchpad.net |
Commit message
Stormify the remaining POTMsgSet filter methods in POFile.
Description of the change
Stormify the remaining POTMsgSet filter methods in POFile. There are no non-cosmetic query changes, but it's much easier to rework the queries to use new denormalised columns.
findPOTMsgSetsC
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/translations/model/pofile.py' |
2 | --- lib/lp/translations/model/pofile.py 2013-06-20 05:50:00 +0000 |
3 | +++ lib/lp/translations/model/pofile.py 2015-02-27 22:28:33 +0000 |
4 | @@ -23,6 +23,7 @@ |
5 | ) |
6 | from storm.expr import ( |
7 | And, |
8 | + Cast, |
9 | Coalesce, |
10 | Desc, |
11 | Exists, |
12 | @@ -267,8 +268,10 @@ |
13 | Orders the result by TranslationTemplateItem.sequence which must |
14 | be among `origin_tables`. |
15 | """ |
16 | + if isinstance(query, basestring): |
17 | + query = SQL(query) |
18 | results = IMasterStore(POTMsgSet).using(origin_tables).find( |
19 | - POTMsgSet, SQL(query)) |
20 | + POTMsgSet, query) |
21 | return results.order_by(TranslationTemplateItem.sequence) |
22 | |
23 | def findPOTMsgSetsContaining(self, text): |
24 | @@ -581,50 +584,42 @@ |
25 | """ |
26 | flag_name = getUtility(ITranslationSideTraitsSet).getForTemplate( |
27 | self.potemplate).flag_name |
28 | - clause_tables = ['TranslationTemplateItem', 'TranslationMessage'] |
29 | - clauses = self._getClausesForPOFileMessages() |
30 | - clauses.append('TranslationMessage.%s IS TRUE' % flag_name) |
31 | - self._appendCompletePluralFormsConditions(clauses) |
32 | + clause_tables = [TranslationTemplateItem, TranslationMessage] |
33 | + clauses = self._getStormClausesForPOFileMessages() |
34 | + clauses.append(getattr(TranslationMessage, flag_name)) |
35 | + clauses.extend( |
36 | + SQL(clause) for clause in self._getCompletePluralFormsConditions()) |
37 | |
38 | # A message is current in this pofile if: |
39 | # * it's current (above) AND |
40 | # * (it's diverged AND non-empty) |
41 | # OR (it's shared AND non-empty AND no diverged one exists) |
42 | - diverged_translation_clauses = [ |
43 | - 'TranslationMessage.potemplate = %s' % sqlvalues(self.potemplate), |
44 | - ] |
45 | - diverged_translation_query = ' AND '.join( |
46 | - diverged_translation_clauses) |
47 | - |
48 | - shared_translation_clauses = [ |
49 | - 'TranslationMessage.potemplate IS NULL', |
50 | - '''NOT EXISTS ( |
51 | - SELECT * FROM TranslationMessage AS diverged |
52 | - WHERE |
53 | - diverged.potemplate=%(potemplate)s AND |
54 | - diverged.%(flag_name)s IS TRUE AND |
55 | - diverged.language = %(language)s AND |
56 | - diverged.potmsgset=TranslationMessage.potmsgset)''' % ( |
57 | - dict( |
58 | - flag_name=flag_name, |
59 | - language=quote(self.language), |
60 | - potemplate=quote(self.potemplate), |
61 | - ) |
62 | - ), |
63 | - ] |
64 | - shared_translation_query = ' AND '.join(shared_translation_clauses) |
65 | - |
66 | - translated_query = ('( (' + diverged_translation_query + ') OR (' |
67 | - + shared_translation_query + ') )') |
68 | - clauses.append(translated_query) |
69 | + diverged_translation_clause = ( |
70 | + TranslationMessage.potemplateID == self.potemplate.id, |
71 | + ) |
72 | + |
73 | + Diverged = ClassAlias(TranslationMessage, 'Diverged') |
74 | + shared_translation_clause = And( |
75 | + TranslationMessage.potemplateID == None, |
76 | + Not(Exists(Select( |
77 | + 1, |
78 | + tables=[Diverged], |
79 | + where=And( |
80 | + Diverged.potmsgsetID == TranslationMessage.potmsgsetID, |
81 | + Diverged.languageID == self.language.id, |
82 | + getattr(Diverged, flag_name), |
83 | + Diverged.potemplateID == self.potemplate.id))))) |
84 | + |
85 | + clauses.append( |
86 | + Or(diverged_translation_clause, shared_translation_clause)) |
87 | return (clauses, clause_tables) |
88 | |
89 | def getPOTMsgSetTranslated(self): |
90 | """See `IPOFile`.""" |
91 | clauses, clause_tables = self._getTranslatedMessagesQuery() |
92 | - clauses.append('TranslationTemplateItem.potmsgset = POTMsgSet.id') |
93 | - |
94 | - query = ' AND '.join(clauses) |
95 | + query = And( |
96 | + TranslationTemplateItem.potmsgsetID == POTMsgSet.id, |
97 | + *clauses) |
98 | clause_tables.insert(0, POTMsgSet) |
99 | return self._getOrderedPOTMsgSets(clause_tables, query) |
100 | |
101 | @@ -633,86 +628,82 @@ |
102 | # We get all POTMsgSet.ids with translations, and later |
103 | # exclude them using a NOT IN subselect. |
104 | translated_clauses, clause_tables = self._getTranslatedMessagesQuery() |
105 | - translated_clauses.append( |
106 | - 'POTMsgSet.id=TranslationTemplateItem.potmsgset') |
107 | - # Even though this seems silly, Postgres prefers |
108 | - # TranslationTemplateItem index if we add it (and on staging we |
109 | - # get more than a 10x speed improvement: from 8s to 0.7s). We |
110 | - # also need to put it before any other clauses to be actually useful. |
111 | - translated_clauses.insert(0, |
112 | - 'TranslationTemplateItem.potmsgset =' |
113 | - ' TranslationTemplateItem.potmsgset') |
114 | - translated_query = ( |
115 | - "(SELECT POTMsgSet.id" |
116 | - " FROM TranslationTemplateItem, TranslationMessage, POTMsgSet" |
117 | - " WHERE " + " AND ".join(translated_clauses) + ")") |
118 | + translated_query = Select( |
119 | + POTMsgSet.id, |
120 | + tables=[TranslationTemplateItem, TranslationMessage, POTMsgSet], |
121 | + where=And( |
122 | + # Even though this seems silly, Postgres prefers |
123 | + # TranslationTemplateItem index if we add it (and on |
124 | + # staging we get more than a 10x speed improvement: from |
125 | + # 8s to 0.7s). We also need to put it before any other |
126 | + # clauses to be actually useful. |
127 | + TranslationTemplateItem.potmsgsetID == |
128 | + TranslationTemplateItem.potmsgsetID, |
129 | + POTMsgSet.id == TranslationTemplateItem.potmsgsetID, |
130 | + *translated_clauses)) |
131 | clauses = [ |
132 | - 'TranslationTemplateItem.potemplate = %s' % sqlvalues( |
133 | - self.potemplate), |
134 | - 'TranslationTemplateItem.potmsgset = POTMsgSet.id', |
135 | - 'TranslationTemplateItem.sequence > 0', |
136 | + TranslationTemplateItem.potemplateID == self.potemplate.id, |
137 | + TranslationTemplateItem.potmsgsetID == POTMsgSet.id, |
138 | + TranslationTemplateItem.sequence > 0, |
139 | + Not(TranslationTemplateItem.potmsgsetID.is_in(translated_query)), |
140 | ] |
141 | - clauses.append( |
142 | - 'TranslationTemplateItem.potmsgset NOT IN (%s)' % ( |
143 | - translated_query)) |
144 | - |
145 | - query = ' AND '.join(clauses) |
146 | return self._getOrderedPOTMsgSets( |
147 | - [POTMsgSet, TranslationTemplateItem], query) |
148 | + [POTMsgSet, TranslationTemplateItem], And(*clauses)) |
149 | |
150 | def getPOTMsgSetWithNewSuggestions(self): |
151 | """See `IPOFile`.""" |
152 | flag_name = getUtility(ITranslationSideTraitsSet).getForTemplate( |
153 | self.potemplate).flag_name |
154 | - clauses = self._getClausesForPOFileMessages() |
155 | - msgstr_clause = make_plurals_sql_fragment( |
156 | - "TranslationMessage.msgstr%(form)d IS NOT NULL", "OR") |
157 | + clauses = self._getStormClausesForPOFileMessages() |
158 | + msgstr_clause = Or(*( |
159 | + getattr(TranslationMessage, 'msgstr%d' % form) != None |
160 | + for form in xrange(TranslationConstants.MAX_PLURAL_FORMS))) |
161 | clauses.extend([ |
162 | - 'TranslationTemplateItem.potmsgset = POTMsgSet.id', |
163 | - 'TranslationMessage.%s IS NOT TRUE' % flag_name, |
164 | - "(%s)" % msgstr_clause, |
165 | + TranslationTemplateItem.potmsgsetID == POTMsgSet.id, |
166 | + Not(getattr(TranslationMessage, flag_name)), |
167 | + msgstr_clause, |
168 | ]) |
169 | |
170 | - diverged_translation_query = ( |
171 | - '''(SELECT COALESCE(diverged.date_reviewed, diverged.date_created) |
172 | - FROM TranslationMessage AS diverged |
173 | - WHERE |
174 | - diverged.%(flag_name)s IS TRUE AND |
175 | - diverged.potemplate = %(potemplate)s AND |
176 | - diverged.language = %(language)s AND |
177 | - diverged.potmsgset=POTMsgSet.id)''' % dict( |
178 | - flag_name=flag_name, |
179 | - potemplate=quote(self.potemplate), |
180 | - language=quote(self.language))) |
181 | - |
182 | - shared_translation_query = ( |
183 | - '''(SELECT COALESCE(shared.date_reviewed, shared.date_created) |
184 | - FROM TranslationMessage AS shared |
185 | - WHERE |
186 | - shared.%(flag_name)s IS TRUE AND |
187 | - shared.potemplate IS NULL AND |
188 | - shared.language = %(language)s AND |
189 | - shared.potmsgset=POTMsgSet.id)''' % dict( |
190 | - flag_name=flag_name, |
191 | - language=quote(self.language))) |
192 | - beginning_of_time = "TIMESTAMP '1970-01-01 00:00:00'" |
193 | - newer_than_query = ( |
194 | - "TranslationMessage.date_created > COALESCE(" + |
195 | - ",".join([diverged_translation_query, |
196 | - shared_translation_query, |
197 | - beginning_of_time]) + ")") |
198 | - clauses.append(newer_than_query) |
199 | + Diverged = ClassAlias(TranslationMessage, "Diverged") |
200 | + diverged_translation_query = Select( |
201 | + Coalesce(Diverged.date_reviewed, Diverged.date_created), |
202 | + tables=[Diverged], |
203 | + where=And( |
204 | + Diverged.potmsgsetID == POTMsgSet.id, |
205 | + Diverged.languageID == self.language.id, |
206 | + getattr(Diverged, flag_name), |
207 | + Diverged.potemplateID == self.potemplate.id)) |
208 | + |
209 | + Shared = ClassAlias(TranslationMessage, "Shared") |
210 | + shared_translation_query = Select( |
211 | + Coalesce(Shared.date_reviewed, Shared.date_created), |
212 | + tables=[Shared], |
213 | + where=And( |
214 | + Shared.potmsgsetID == POTMsgSet.id, |
215 | + Shared.languageID == self.language.id, |
216 | + getattr(Shared, flag_name), |
217 | + Shared.potemplateID == None)) |
218 | + |
219 | + beginning_of_time = Cast(u'1970-01-01 00:00:00', 'timestamp') |
220 | + clauses.append( |
221 | + TranslationMessage.date_created > |
222 | + Coalesce( |
223 | + diverged_translation_query, shared_translation_query, |
224 | + beginning_of_time)) |
225 | |
226 | # A POT set has "new" suggestions if there is a non current |
227 | # TranslationMessage newer than the current reviewed one. |
228 | - query = ( |
229 | - """POTMsgSet.id IN (SELECT DISTINCT TranslationMessage.potmsgset |
230 | - FROM TranslationMessage, TranslationTemplateItem, POTMsgSet |
231 | - WHERE (%(query)s)) AND |
232 | - POTMsgSet.id=TranslationTemplateItem.potmsgset AND |
233 | - TranslationTemplateItem.potemplate=%(potemplate)s |
234 | - """ % dict(query=' AND '.join(clauses), |
235 | - potemplate=quote(self.potemplate))) |
236 | + query = And( |
237 | + POTMsgSet.id.is_in( |
238 | + Select( |
239 | + TranslationMessage.potmsgsetID, |
240 | + tables=[ |
241 | + TranslationMessage, TranslationTemplateItem, |
242 | + POTMsgSet], |
243 | + where=And(*clauses), |
244 | + distinct=True)), |
245 | + POTMsgSet.id == TranslationTemplateItem.potmsgsetID, |
246 | + TranslationTemplateItem.potemplateID == self.potemplate.id) |
247 | return self._getOrderedPOTMsgSets( |
248 | [POTMsgSet, TranslationTemplateItem], query) |
249 | |
250 | @@ -727,44 +718,39 @@ |
251 | ITranslationSideTraitsSet).getForTemplate( |
252 | self.potemplate).other_side_traits.flag_name |
253 | clauses.extend([ |
254 | - 'TranslationTemplateItem.potmsgset = POTMsgSet.id', |
255 | - 'TranslationMessage.%s IS FALSE' % other_side_flag_name, |
256 | + TranslationTemplateItem.potmsgsetID == POTMsgSet.id, |
257 | + Not(getattr(TranslationMessage, other_side_flag_name)), |
258 | ]) |
259 | |
260 | - imported_no_diverged = ( |
261 | - '''NOT EXISTS ( |
262 | - SELECT * FROM TranslationMessage AS diverged |
263 | - WHERE |
264 | - diverged.%(flag_name)s IS TRUE AND |
265 | - diverged.id <> imported.id AND |
266 | - diverged.potemplate = %(potemplate)s AND |
267 | - diverged.language = %(language)s AND |
268 | - diverged.potmsgset=TranslationMessage.potmsgset)''' % ( |
269 | - dict( |
270 | - flag_name=other_side_flag_name, |
271 | - potemplate=quote(self.potemplate), |
272 | - language=quote(self.language), |
273 | - ))) |
274 | + Imported = ClassAlias(TranslationMessage, 'Imported') |
275 | + Diverged = ClassAlias(TranslationMessage, 'Diverged') |
276 | + imported_no_diverged = Not(Exists( |
277 | + Select( |
278 | + 1, |
279 | + tables=[Diverged], |
280 | + where=And( |
281 | + Diverged.id != Imported.id, |
282 | + Diverged.potmsgsetID == TranslationMessage.potmsgsetID, |
283 | + Diverged.languageID == self.language.id, |
284 | + getattr(Diverged, other_side_flag_name), |
285 | + Diverged.potemplateID == self.potemplate.id)))) |
286 | imported_clauses = [ |
287 | - 'imported.id <> TranslationMessage.id', |
288 | - 'imported.potmsgset = POTMsgSet.id', |
289 | - 'imported.language = %s' % sqlvalues(self.language), |
290 | - 'imported.%s IS TRUE' % other_side_flag_name, |
291 | - '(imported.potemplate=%s OR ' % sqlvalues(self.potemplate) + |
292 | - ' (imported.potemplate IS NULL AND ' + imported_no_diverged |
293 | - + ' ))', |
294 | + Imported.id != TranslationMessage.id, |
295 | + Imported.potmsgsetID == POTMsgSet.id, |
296 | + Imported.languageID == self.language.id, |
297 | + getattr(Imported, other_side_flag_name), |
298 | + Or( |
299 | + Imported.potemplateID == self.potemplate.id, |
300 | + And(Imported.potemplateID == None, imported_no_diverged)), |
301 | ] |
302 | - self._appendCompletePluralFormsConditions(imported_clauses, |
303 | - 'imported') |
304 | - exists_imported_query = ( |
305 | - 'EXISTS (' |
306 | - ' SELECT * FROM TranslationMessage AS imported' |
307 | - ' WHERE ' + ' AND '.join(imported_clauses) + ')') |
308 | - clauses.append(exists_imported_query) |
309 | + imported_clauses.extend( |
310 | + SQL(clause) for clause in |
311 | + self._getCompletePluralFormsConditions('imported')) |
312 | + clauses.append(Exists(Select( |
313 | + 1, tables=[Imported], where=And(*imported_clauses)))) |
314 | |
315 | clause_tables.insert(0, POTMsgSet) |
316 | - query = ' AND '.join(clauses) |
317 | - return self._getOrderedPOTMsgSets(clause_tables, query) |
318 | + return self._getOrderedPOTMsgSets(clause_tables, And(*clauses)) |
319 | |
320 | def messageCount(self): |
321 | """See `IRosettaStats`.""" |
322 | @@ -794,16 +780,17 @@ |
323 | self.rosettacount, |
324 | self.unreviewed_count) |
325 | |
326 | - def _appendCompletePluralFormsConditions(self, query, |
327 | - table_name='TranslationMessage'): |
328 | + def _getCompletePluralFormsConditions(self, |
329 | + table_name='TranslationMessage'): |
330 | """Add conditions to implement ITranslationMessage.is_complete in SQL. |
331 | |
332 | :param query: A list of AND SQL conditions where the implementation of |
333 | ITranslationMessage.is_complete will be appended as SQL |
334 | conditions. |
335 | """ |
336 | - query.append('%(table_name)s.msgstr0 IS NOT NULL' % { |
337 | - 'table_name': table_name}) |
338 | + query = [ |
339 | + '%(table_name)s.msgstr0 IS NOT NULL' % {'table_name': table_name}, |
340 | + ] |
341 | if self.language.pluralforms > 1: |
342 | plurals_query = ' AND '.join( |
343 | '%(table_name)s.msgstr%(plural_form)d IS NOT NULL' % { |
344 | @@ -825,11 +812,9 @@ |
345 | side_traits = getUtility(ITranslationSideTraitsSet).getForTemplate( |
346 | self.potemplate) |
347 | complete_plural_clause_this_side = ' AND '.join( |
348 | - self._appendCompletePluralFormsConditions( |
349 | - [], table_name='Current')) |
350 | + self._getCompletePluralFormsConditions(table_name='Current')) |
351 | complete_plural_clause_other_side = ' AND '.join( |
352 | - self._appendCompletePluralFormsConditions( |
353 | - [], table_name='Other')) |
354 | + self._getCompletePluralFormsConditions(table_name='Other')) |
355 | params = { |
356 | 'potemplate': quote(self.potemplate), |
357 | 'language': quote(self.language), |
I believe that you can remove the _getClausesForP OFileMessages method now too.