blob: 7ee15983a453809c5426067c2af162eefd64b194 [file] [log] [blame]
showard35444862008-08-07 22:35:30 +00001from django.db import models as dbmodels, connection
2from django.utils import datastructures
3from autotest_lib.frontend.afe import model_logic, readonly_connection
4
5class TempManager(model_logic.ExtendedManager):
6 _GROUP_COUNT_NAME = 'group_count'
7
8 def _get_key_unless_is_function(self, field):
9 if '(' in field:
10 return field
showard7c199df2008-10-03 10:17:15 +000011 return self.get_key_on_this_table(field)
showard35444862008-08-07 22:35:30 +000012
13
showardf2489522008-10-23 23:08:00 +000014 def _get_field_names(self, fields, extra_select_fields={}):
15 field_names = []
16 for field in fields:
17 if field in extra_select_fields:
18 field_names.append(field)
19 else:
20 field_names.append(self._get_key_unless_is_function(field))
21 return field_names
showard35444862008-08-07 22:35:30 +000022
23
24 def _get_group_query_sql(self, query, group_by, extra_select_fields):
showardf2489522008-10-23 23:08:00 +000025 group_fields = self._get_field_names(group_by, extra_select_fields)
showard35444862008-08-07 22:35:30 +000026
showarda5288b42009-07-28 20:06:08 +000027 # Clone the queryset, so that we don't change the original
28 query = query.all()
showard35444862008-08-07 22:35:30 +000029
showarda5288b42009-07-28 20:06:08 +000030 # In order to use query.extra(), we need to first clear the limits
31 # and then add them back in after the extra
32 low = query.query.low_mark
33 high = query.query.high_mark
34 query.query.clear_limits()
35
36 select_fields = dict(
37 (field_name, self._get_key_unless_is_function(field_sql))
38 for field_name, field_sql in extra_select_fields.iteritems())
39 query = query.extra(select=select_fields)
40
41 query.query.set_limits(low=low, high=high)
42
43 sql, params = query.query.as_sql()
showardd50ffb42008-09-04 02:47:45 +000044
45 # insert GROUP BY clause into query
showard7c199df2008-10-03 10:17:15 +000046 group_by_clause = ' GROUP BY ' + ', '.join(group_fields)
showarda5288b42009-07-28 20:06:08 +000047 group_by_position = sql.rfind('ORDER BY')
showardd50ffb42008-09-04 02:47:45 +000048 if group_by_position == -1:
showarda5288b42009-07-28 20:06:08 +000049 group_by_position = len(sql)
50 sql = (sql[:group_by_position] +
51 group_by_clause + ' ' +
52 sql[group_by_position:])
showard35444862008-08-07 22:35:30 +000053
showarda5288b42009-07-28 20:06:08 +000054 return sql, params
showard35444862008-08-07 22:35:30 +000055
56
showard06b82fc2009-06-30 01:59:42 +000057 def _get_column_names(self, cursor):
58 """\
59 Gets the column names from the cursor description. This method exists
60 so that it can be mocked in the unit test for sqlite3 compatibility."
61 """
62 return [column_info[0] for column_info in cursor.description]
63
64
showard8a6eb0c2008-10-01 11:38:59 +000065 def execute_group_query(self, query, group_by, extra_select_fields=[]):
showard35444862008-08-07 22:35:30 +000066 """
showard8a6eb0c2008-10-01 11:38:59 +000067 Performs the given query grouped by the fields in group_by with the
showard7c199df2008-10-03 10:17:15 +000068 given extra select fields added. extra_select_fields should be a dict
69 mapping field alias to field SQL. Usually, the extra fields will use
showard8a6eb0c2008-10-01 11:38:59 +000070 group aggregation functions. Returns a list of dicts, where each dict
71 corresponds to single row and contains a key for each grouped field as
72 well as all of the extra select fields.
showard35444862008-08-07 22:35:30 +000073 """
74 sql, params = self._get_group_query_sql(query, group_by,
75 extra_select_fields)
showard56e93772008-10-06 10:06:22 +000076 cursor = readonly_connection.connection().cursor()
showard8a6eb0c2008-10-01 11:38:59 +000077 cursor.execute(sql, params)
showard06b82fc2009-06-30 01:59:42 +000078 field_names = self._get_column_names(cursor)
showard8a6eb0c2008-10-01 11:38:59 +000079 row_dicts = [dict(zip(field_names, row)) for row in cursor.fetchall()]
80 return row_dicts
81
82
83 def get_count_sql(self, query):
84 """
85 Get the SQL to properly select a per-group count of unique matches for
showard7c199df2008-10-03 10:17:15 +000086 a grouped query. Returns a tuple (field alias, field SQL)
showard8a6eb0c2008-10-01 11:38:59 +000087 """
showarda5288b42009-07-28 20:06:08 +000088 if query.query.distinct:
showard7c199df2008-10-03 10:17:15 +000089 pk_field = self.get_key_on_this_table()
showard8a6eb0c2008-10-01 11:38:59 +000090 count_sql = 'COUNT(DISTINCT %s)' % pk_field
91 else:
92 count_sql = 'COUNT(1)'
showard7c199df2008-10-03 10:17:15 +000093 return self._GROUP_COUNT_NAME, count_sql
showard35444862008-08-07 22:35:30 +000094
95
96 def _get_num_groups_sql(self, query, group_by):
97 group_fields = self._get_field_names(group_by)
showarda5288b42009-07-28 20:06:08 +000098 query = query.order_by() # this can mess up the query and isn't needed
99
100 sql, params = query.query.as_sql()
101 from_ = sql[sql.find(' FROM'):]
showard35444862008-08-07 22:35:30 +0000102 return ('SELECT COUNT(DISTINCT %s) %s' % (','.join(group_fields),
showarda5288b42009-07-28 20:06:08 +0000103 from_),
showard35444862008-08-07 22:35:30 +0000104 params)
105
106
107 def get_num_groups(self, query, group_by):
108 """
109 Returns the number of distinct groups for the given query grouped by the
110 fields in group_by.
111 """
112 sql, params = self._get_num_groups_sql(query, group_by)
showard56e93772008-10-06 10:06:22 +0000113 cursor = readonly_connection.connection().cursor()
showard35444862008-08-07 22:35:30 +0000114 cursor.execute(sql, params)
115 return cursor.fetchone()[0]
116
117
118class Machine(dbmodels.Model):
showardf8b19042009-05-12 17:22:49 +0000119 machine_idx = dbmodels.AutoField(primary_key=True)
showarda5288b42009-07-28 20:06:08 +0000120 hostname = dbmodels.CharField(unique=True, max_length=300)
121 machine_group = dbmodels.CharField(blank=True, max_length=240)
122 owner = dbmodels.CharField(blank=True, max_length=240)
showard35444862008-08-07 22:35:30 +0000123
124 class Meta:
125 db_table = 'machines'
126
127
128class Kernel(dbmodels.Model):
showardf8b19042009-05-12 17:22:49 +0000129 kernel_idx = dbmodels.AutoField(primary_key=True)
showarda5288b42009-07-28 20:06:08 +0000130 kernel_hash = dbmodels.CharField(max_length=105, editable=False)
131 base = dbmodels.CharField(max_length=90)
132 printable = dbmodels.CharField(max_length=300)
showard35444862008-08-07 22:35:30 +0000133
134 class Meta:
135 db_table = 'kernels'
136
137
138class Patch(dbmodels.Model):
139 kernel = dbmodels.ForeignKey(Kernel, db_column='kernel_idx')
showarda5288b42009-07-28 20:06:08 +0000140 name = dbmodels.CharField(blank=True, max_length=240)
141 url = dbmodels.CharField(blank=True, max_length=900)
142 the_hash = dbmodels.CharField(blank=True, max_length=105, db_column='hash')
showard35444862008-08-07 22:35:30 +0000143
144 class Meta:
145 db_table = 'patches'
146
147
148class Status(dbmodels.Model):
showardf8b19042009-05-12 17:22:49 +0000149 status_idx = dbmodels.AutoField(primary_key=True)
showarda5288b42009-07-28 20:06:08 +0000150 word = dbmodels.CharField(max_length=30)
showard35444862008-08-07 22:35:30 +0000151
152 class Meta:
153 db_table = 'status'
154
155
156class Job(dbmodels.Model):
showardf8b19042009-05-12 17:22:49 +0000157 job_idx = dbmodels.AutoField(primary_key=True)
showarda5288b42009-07-28 20:06:08 +0000158 tag = dbmodels.CharField(unique=True, max_length=300)
159 label = dbmodels.CharField(max_length=300)
160 username = dbmodels.CharField(max_length=240)
showard35444862008-08-07 22:35:30 +0000161 machine = dbmodels.ForeignKey(Machine, db_column='machine_idx')
162 queued_time = dbmodels.DateTimeField(null=True, blank=True)
163 started_time = dbmodels.DateTimeField(null=True, blank=True)
164 finished_time = dbmodels.DateTimeField(null=True, blank=True)
165
166 class Meta:
167 db_table = 'jobs'
168
169
showardf8b19042009-05-12 17:22:49 +0000170class Test(dbmodels.Model, model_logic.ModelExtensions,
171 model_logic.ModelWithAttributes):
172 test_idx = dbmodels.AutoField(primary_key=True)
showard35444862008-08-07 22:35:30 +0000173 job = dbmodels.ForeignKey(Job, db_column='job_idx')
showarda5288b42009-07-28 20:06:08 +0000174 test = dbmodels.CharField(max_length=90)
175 subdir = dbmodels.CharField(blank=True, max_length=180)
showard35444862008-08-07 22:35:30 +0000176 kernel = dbmodels.ForeignKey(Kernel, db_column='kernel_idx')
177 status = dbmodels.ForeignKey(Status, db_column='status')
showarda5288b42009-07-28 20:06:08 +0000178 reason = dbmodels.CharField(blank=True, max_length=3072)
showard35444862008-08-07 22:35:30 +0000179 machine = dbmodels.ForeignKey(Machine, db_column='machine_idx')
180 finished_time = dbmodels.DateTimeField(null=True, blank=True)
181 started_time = dbmodels.DateTimeField(null=True, blank=True)
182
showardf8b19042009-05-12 17:22:49 +0000183 objects = model_logic.ExtendedManager()
184
185 def _get_attribute_model_and_args(self, attribute):
186 return TestAttribute, dict(test=self, attribute=attribute,
187 user_created=True)
188
189
190 def set_attribute(self, attribute, value):
191 # ensure non-user-created attributes remain immutable
192 try:
193 TestAttribute.objects.get(test=self, attribute=attribute,
194 user_created=False)
195 raise ValueError('Attribute %s already exists for test %s and is '
196 'immutable' % (attribute, self.test_idx))
197 except TestAttribute.DoesNotExist:
198 super(Test, self).set_attribute(attribute, value)
199
200
showard35444862008-08-07 22:35:30 +0000201 class Meta:
202 db_table = 'tests'
203
204
showarde732ee72008-09-23 19:15:43 +0000205class TestAttribute(dbmodels.Model, model_logic.ModelExtensions):
showardf8b19042009-05-12 17:22:49 +0000206 test = dbmodels.ForeignKey(Test, db_column='test_idx')
showarda5288b42009-07-28 20:06:08 +0000207 attribute = dbmodels.CharField(max_length=90)
208 value = dbmodels.CharField(blank=True, max_length=300)
showardf8b19042009-05-12 17:22:49 +0000209 user_created = dbmodels.BooleanField(default=False)
210
211 objects = model_logic.ExtendedManager()
showard35444862008-08-07 22:35:30 +0000212
213 class Meta:
214 db_table = 'test_attributes'
215
216
jadmanski430dca92008-12-16 20:56:53 +0000217class IterationAttribute(dbmodels.Model, model_logic.ModelExtensions):
showardf8b19042009-05-12 17:22:49 +0000218 # this isn't really a primary key, but it's necessary to appease Django
219 # and is harmless as long as we're careful
showarde732ee72008-09-23 19:15:43 +0000220 test = dbmodels.ForeignKey(Test, db_column='test_idx', primary_key=True)
showard35444862008-08-07 22:35:30 +0000221 iteration = dbmodels.IntegerField()
showarda5288b42009-07-28 20:06:08 +0000222 attribute = dbmodels.CharField(max_length=90)
223 value = dbmodels.CharField(blank=True, max_length=300)
showard35444862008-08-07 22:35:30 +0000224
showardf8b19042009-05-12 17:22:49 +0000225 objects = model_logic.ExtendedManager()
226
showard35444862008-08-07 22:35:30 +0000227 class Meta:
228 db_table = 'iteration_attributes'
229
230
jadmanski430dca92008-12-16 20:56:53 +0000231class IterationResult(dbmodels.Model, model_logic.ModelExtensions):
showardf8b19042009-05-12 17:22:49 +0000232 # see comment on IterationAttribute regarding primary_key=True
jadmanski430dca92008-12-16 20:56:53 +0000233 test = dbmodels.ForeignKey(Test, db_column='test_idx', primary_key=True)
showard35444862008-08-07 22:35:30 +0000234 iteration = dbmodels.IntegerField()
showarda5288b42009-07-28 20:06:08 +0000235 attribute = dbmodels.CharField(max_length=90)
236 value = dbmodels.DecimalField(null=True, max_digits=12, decimal_places=31,
237 blank=True)
showard35444862008-08-07 22:35:30 +0000238
showardf8b19042009-05-12 17:22:49 +0000239 objects = model_logic.ExtendedManager()
240
showard35444862008-08-07 22:35:30 +0000241 class Meta:
242 db_table = 'iteration_result'
243
244
245class TestLabel(dbmodels.Model, model_logic.ModelExtensions):
showarda5288b42009-07-28 20:06:08 +0000246 name = dbmodels.CharField(max_length=80, unique=True)
showard35444862008-08-07 22:35:30 +0000247 description = dbmodels.TextField(blank=True)
showarda5288b42009-07-28 20:06:08 +0000248 tests = dbmodels.ManyToManyField(Test, blank=True)
showard35444862008-08-07 22:35:30 +0000249
250 name_field = 'name'
showardf8b19042009-05-12 17:22:49 +0000251 objects = model_logic.ExtendedManager()
showard35444862008-08-07 22:35:30 +0000252
253 class Meta:
254 db_table = 'test_labels'
255
256
257class SavedQuery(dbmodels.Model, model_logic.ModelExtensions):
258 # TODO: change this to foreign key once DBs are merged
showarda5288b42009-07-28 20:06:08 +0000259 owner = dbmodels.CharField(max_length=80)
260 name = dbmodels.CharField(max_length=100)
showard35444862008-08-07 22:35:30 +0000261 url_token = dbmodels.TextField()
262
263 class Meta:
264 db_table = 'saved_queries'
265
266
showardce12f552008-09-19 00:48:59 +0000267class EmbeddedGraphingQuery(dbmodels.Model, model_logic.ModelExtensions):
268 url_token = dbmodels.TextField(null=False, blank=False)
showarda5288b42009-07-28 20:06:08 +0000269 graph_type = dbmodels.CharField(max_length=16, null=False, blank=False)
showardce12f552008-09-19 00:48:59 +0000270 params = dbmodels.TextField(null=False, blank=False)
271 last_updated = dbmodels.DateTimeField(null=False, blank=False,
272 editable=False)
273 # refresh_time shows the time at which a thread is updating the cached
274 # image, or NULL if no one is updating the image. This is used so that only
275 # one thread is updating the cached image at a time (see
276 # graphing_utils.handle_plot_request)
277 refresh_time = dbmodels.DateTimeField(editable=False)
278 cached_png = dbmodels.TextField(editable=False)
279
280 class Meta:
281 db_table = 'embedded_graphing_queries'
282
283
showard35444862008-08-07 22:35:30 +0000284# views
285
286class TestViewManager(TempManager):
showard35444862008-08-07 22:35:30 +0000287 def get_query_set(self):
288 query = super(TestViewManager, self).get_query_set()
showard5bf7c502008-08-20 01:22:22 +0000289
showard35444862008-08-07 22:35:30 +0000290 # add extra fields to selects, using the SQL itself as the "alias"
291 extra_select = dict((sql, sql)
292 for sql in self.model.extra_fields.iterkeys())
293 return query.extra(select=extra_select)
294
295
showardf2489522008-10-23 23:08:00 +0000296 def _get_include_exclude_suffix(self, exclude):
297 if exclude:
298 suffix = '_exclude'
299 else:
300 suffix = '_include'
301 return suffix
302
303
showard64aeecd2008-09-19 21:32:58 +0000304 def _add_label_joins(self, query_set, suffix=''):
showard43a3d262008-11-12 18:17:05 +0000305 query_set = self.add_join(query_set, 'test_labels_tests',
showarda5288b42009-07-28 20:06:08 +0000306 join_key='test_id', suffix=suffix,
307 force_left_join=True)
showardd50ffb42008-09-04 02:47:45 +0000308
309 second_join_alias = 'test_labels' + suffix
310 second_join_condition = ('%s.id = %s.testlabel_id' %
showard64aeecd2008-09-19 21:32:58 +0000311 (second_join_alias,
312 'test_labels_tests' + suffix))
313 filter_object = self._CustomSqlQ()
showardd50ffb42008-09-04 02:47:45 +0000314 filter_object.add_join('test_labels',
315 second_join_condition,
showarda5288b42009-07-28 20:06:08 +0000316 query_set.query.LOUTER,
showardd50ffb42008-09-04 02:47:45 +0000317 alias=second_join_alias)
showarda5288b42009-07-28 20:06:08 +0000318 return self._add_customSqlQ(query_set, filter_object)
showardd50ffb42008-09-04 02:47:45 +0000319
showard64aeecd2008-09-19 21:32:58 +0000320
showardf2489522008-10-23 23:08:00 +0000321 def _add_attribute_join(self, query_set, join_condition='', suffix=None,
showard64aeecd2008-09-19 21:32:58 +0000322 exclude=False):
showard93caf2d2009-05-08 18:24:22 +0000323 join_condition = self.escape_user_sql(join_condition)
showardf2489522008-10-23 23:08:00 +0000324 if suffix is None:
325 suffix = self._get_include_exclude_suffix(exclude)
showard43a3d262008-11-12 18:17:05 +0000326 return self.add_join(query_set, 'test_attributes',
327 join_key='test_idx',
showard64aeecd2008-09-19 21:32:58 +0000328 join_condition=join_condition,
329 suffix=suffix, exclude=exclude)
showardd50ffb42008-09-04 02:47:45 +0000330
331
332 def _get_label_ids_from_names(self, label_names):
showard64aeecd2008-09-19 21:32:58 +0000333 if not label_names:
334 return []
showardd50ffb42008-09-04 02:47:45 +0000335 query = TestLabel.objects.filter(name__in=label_names).values('id')
showardfc8c6ae2008-11-11 19:06:01 +0000336 return [str(label['id']) for label in query]
showard02813502008-08-20 20:52:56 +0000337
338
showardf2489522008-10-23 23:08:00 +0000339 def get_query_set_with_joins(self, filter_data, include_host_labels=False):
showardfc8c6ae2008-11-11 19:06:01 +0000340 include_labels = filter_data.pop('include_labels', [])
showardd50ffb42008-09-04 02:47:45 +0000341 exclude_labels = filter_data.pop('exclude_labels', [])
showard35444862008-08-07 22:35:30 +0000342 query_set = self.get_query_set()
showardd50ffb42008-09-04 02:47:45 +0000343 joined = False
showard35444862008-08-07 22:35:30 +0000344 # TODO: make this check more thorough if necessary
showardf2489522008-10-23 23:08:00 +0000345 extra_where = filter_data.get('extra_where', '')
346 if 'test_labels' in extra_where:
showard02813502008-08-20 20:52:56 +0000347 query_set = self._add_label_joins(query_set)
showardd50ffb42008-09-04 02:47:45 +0000348 joined = True
349
showardfc8c6ae2008-11-11 19:06:01 +0000350 include_label_ids = self._get_label_ids_from_names(include_labels)
351 if include_label_ids:
352 # TODO: Factor this out like what's done with attributes
353 condition = ('test_labels_tests_include.testlabel_id IN (%s)' %
354 ','.join(include_label_ids))
showard43a3d262008-11-12 18:17:05 +0000355 query_set = self.add_join(query_set, 'test_labels_tests',
showardfc8c6ae2008-11-11 19:06:01 +0000356 join_key='test_id',
357 suffix='_include',
358 join_condition=condition)
359 joined = True
360
showard64aeecd2008-09-19 21:32:58 +0000361 exclude_label_ids = self._get_label_ids_from_names(exclude_labels)
362 if exclude_label_ids:
363 condition = ('test_labels_tests_exclude.testlabel_id IN (%s)' %
showardfc8c6ae2008-11-11 19:06:01 +0000364 ','.join(exclude_label_ids))
showard43a3d262008-11-12 18:17:05 +0000365 query_set = self.add_join(query_set, 'test_labels_tests',
showard64aeecd2008-09-19 21:32:58 +0000366 join_key='test_id',
367 suffix='_exclude',
368 join_condition=condition,
369 exclude=True)
370 joined = True
371
372 include_attributes_where = filter_data.pop('include_attributes_where',
373 '')
374 exclude_attributes_where = filter_data.pop('exclude_attributes_where',
375 '')
376 if include_attributes_where:
377 query_set = self._add_attribute_join(
showardf2489522008-10-23 23:08:00 +0000378 query_set, join_condition=include_attributes_where)
showard64aeecd2008-09-19 21:32:58 +0000379 joined = True
380 if exclude_attributes_where:
381 query_set = self._add_attribute_join(
showardf2489522008-10-23 23:08:00 +0000382 query_set, join_condition=exclude_attributes_where,
showard64aeecd2008-09-19 21:32:58 +0000383 exclude=True)
384 joined = True
showardd50ffb42008-09-04 02:47:45 +0000385
386 if not joined:
showard35444862008-08-07 22:35:30 +0000387 filter_data['no_distinct'] = True
showardd50ffb42008-09-04 02:47:45 +0000388
showardf2489522008-10-23 23:08:00 +0000389 if include_host_labels or 'test_attributes_host_labels' in extra_where:
390 query_set = self._add_attribute_join(
391 query_set, suffix='_host_labels',
392 join_condition='test_attributes_host_labels.attribute = '
393 '"host-labels"')
394
showard35444862008-08-07 22:35:30 +0000395 return query_set
396
397
showard02813502008-08-20 20:52:56 +0000398 def query_test_ids(self, filter_data):
399 dicts = self.model.query_objects(filter_data).values('test_idx')
400 return [item['test_idx'] for item in dicts]
401
402
showard02813502008-08-20 20:52:56 +0000403 def query_test_label_ids(self, filter_data):
showardd50ffb42008-09-04 02:47:45 +0000404 query_set = self.model.query_objects(filter_data)
405 query_set = self._add_label_joins(query_set, suffix='_list')
406 rows = self._custom_select_query(query_set, ['test_labels_list.id'])
407 return [row[0] for row in rows if row[0] is not None]
showard02813502008-08-20 20:52:56 +0000408
409
showardeaccf8f2009-04-16 03:11:33 +0000410 def escape_user_sql(self, sql):
411 sql = super(TestViewManager, self).escape_user_sql(sql)
412 return sql.replace('test_idx', self.get_key_on_this_table('test_idx'))
413
414
showard35444862008-08-07 22:35:30 +0000415class TestView(dbmodels.Model, model_logic.ModelExtensions):
416 extra_fields = {
showardf4c702e2009-07-08 21:14:27 +0000417 'DATE(job_queued_time)': 'job queued day',
418 'DATE(test_finished_time)': 'test finished day',
showard35444862008-08-07 22:35:30 +0000419 }
420
421 group_fields = [
showardf4c702e2009-07-08 21:14:27 +0000422 'test_name',
423 'status',
424 'kernel',
425 'hostname',
426 'job_tag',
427 'job_name',
428 'platform',
429 'reason',
430 'job_owner',
431 'job_queued_time',
432 'DATE(job_queued_time)',
433 'test_started_time',
434 'test_finished_time',
435 'DATE(test_finished_time)',
showard35444862008-08-07 22:35:30 +0000436 ]
437
438 test_idx = dbmodels.IntegerField('test index', primary_key=True)
439 job_idx = dbmodels.IntegerField('job index', null=True, blank=True)
showarda5288b42009-07-28 20:06:08 +0000440 test_name = dbmodels.CharField(blank=True, max_length=90)
441 subdir = dbmodels.CharField('subdirectory', blank=True, max_length=180)
showard35444862008-08-07 22:35:30 +0000442 kernel_idx = dbmodels.IntegerField('kernel index')
443 status_idx = dbmodels.IntegerField('status index')
showarda5288b42009-07-28 20:06:08 +0000444 reason = dbmodels.CharField(blank=True, max_length=3072)
showard35444862008-08-07 22:35:30 +0000445 machine_idx = dbmodels.IntegerField('host index')
446 test_started_time = dbmodels.DateTimeField(null=True, blank=True)
447 test_finished_time = dbmodels.DateTimeField(null=True, blank=True)
showarda5288b42009-07-28 20:06:08 +0000448 job_tag = dbmodels.CharField(blank=True, max_length=300)
449 job_name = dbmodels.CharField(blank=True, max_length=300)
450 job_owner = dbmodels.CharField('owner', blank=True, max_length=240)
showard35444862008-08-07 22:35:30 +0000451 job_queued_time = dbmodels.DateTimeField(null=True, blank=True)
452 job_started_time = dbmodels.DateTimeField(null=True, blank=True)
453 job_finished_time = dbmodels.DateTimeField(null=True, blank=True)
showarda5288b42009-07-28 20:06:08 +0000454 hostname = dbmodels.CharField(blank=True, max_length=300)
455 platform = dbmodels.CharField(blank=True, max_length=240)
456 machine_owner = dbmodels.CharField(blank=True, max_length=240)
457 kernel_hash = dbmodels.CharField(blank=True, max_length=105)
458 kernel_base = dbmodels.CharField(blank=True, max_length=90)
459 kernel = dbmodels.CharField(blank=True, max_length=300)
460 status = dbmodels.CharField(blank=True, max_length=30)
showard35444862008-08-07 22:35:30 +0000461
462 objects = TestViewManager()
463
464 def save(self):
465 raise NotImplementedError('TestView is read-only')
466
467
468 def delete(self):
469 raise NotImplementedError('TestView is read-only')
470
471
472 @classmethod
473 def query_objects(cls, filter_data, initial_query=None):
474 if initial_query is None:
showard64aeecd2008-09-19 21:32:58 +0000475 initial_query = cls.objects.get_query_set_with_joins(filter_data)
showard35444862008-08-07 22:35:30 +0000476 return super(TestView, cls).query_objects(filter_data,
477 initial_query=initial_query)
478
479
480 @classmethod
showarde732ee72008-09-23 19:15:43 +0000481 def list_objects(cls, filter_data, initial_query=None, fields=None):
482 # include extra fields
483 if fields is None:
484 fields = cls.get_field_dict().keys() + cls.extra_fields.keys()
485 return super(TestView, cls).list_objects(filter_data, initial_query,
486 fields)
showard35444862008-08-07 22:35:30 +0000487
488
489 class Meta:
490 db_table = 'test_view_2'