Use Field.sql_column for SELECT queries in ModelSQL

By using sql_column, it increases the possibilities of customisation of fields.

issue4369
review14711002
This commit is contained in:
Cédric Krier
2014-12-20 19:24:42 +01:00
parent 59afe32b76
commit 67d5291bfd
3 changed files with 18 additions and 8 deletions
+2 -1
View File
@@ -179,7 +179,8 @@ class Database(DatabaseInterface):
raise IOError('Database "%s" doesn\'t exist!' % db_filename)
if self._conn is not None:
return self
self._conn = sqlite.connect(path, detect_types=sqlite.PARSE_DECLTYPES)
self._conn = sqlite.connect(path,
detect_types=sqlite.PARSE_DECLTYPES | sqlite.PARSE_COLNAMES)
self._conn.create_function('extract', 2, SQLiteExtract.extract)
self._conn.create_function('date_trunc', 2, date_trunc)
self._conn.create_function('split_part', 3, split_part)
+9 -2
View File
@@ -1,13 +1,20 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from decimal import Decimal
from sql import Query, Expression, Cast, Literal, Select, CombiningQuery
from sql import Query, Expression, Cast, Literal, Select, CombiningQuery, As
from ... import backend
from .field import SQLType
from .float import Float
class SQLite_Cast(Cast):
def as_(self, output_name):
# Use PARSE_COLNAMES instead of CAST for final column
return As(self.expression, '%s [NUMERIC]' % output_name)
class Numeric(Float):
'''
Define a numeric field (``decimal``).
@@ -36,7 +43,7 @@ class Numeric(Float):
db_type = backend.name()
if db_type == 'sqlite':
# Must be casted as Decimal is stored as bytes
column = Cast(column, self.sql_type().base)
column = SQLite_Cast(column, self.sql_type().base)
return column
def _domain_value(self, operator, value):
+7 -5
View File
@@ -567,8 +567,9 @@ class ModelSQL(ModelStorage):
columns = []
for f in fields_names + fields_related.keys() + datetime_fields:
if (f in cls._fields and not hasattr(cls._fields[f], 'set')):
columns.append(Column(table, f).as_(f))
field = cls._fields.get(f)
if field and not hasattr(field, 'set'):
columns.append(field.sql_column(table).as_(f))
elif f == '_timestamp' and not table_query:
sql_type = fields.Char('timestamp').sql_type().base
columns.append(Extract('EPOCH',
@@ -609,7 +610,8 @@ class ModelSQL(ModelStorage):
result = [{'id': x} for x in ids]
for column in columns:
field = column.output_name
# Split the output name to remove SQLite type detection
field = column.output_name.split()[0]
if field == '_timestamp':
continue
if (getattr(cls._fields[field], 'translate', False)
@@ -873,7 +875,7 @@ class ModelSQL(ModelStorage):
and field.left and field.right):
tree_ids[fname] = []
for sub_ids in grouped_slice(ids):
where = reduce_ids(Column(table, fname), sub_ids)
where = reduce_ids(field.sql_column(table), sub_ids)
cursor.execute(*table.select(table.id, where=where))
tree_ids[fname] += [x[0] for x in cursor.fetchall()]
@@ -1035,7 +1037,7 @@ class ModelSQL(ModelStorage):
main_table.create_date).as_('_datetime'))
columns.append(Column(main_table, '__id'))
if not query:
columns += [Column(main_table, n).as_(n)
columns += [f.sql_column(main_table).as_(n)
for n, f in cls._fields.iteritems()
if not hasattr(f, 'get')
and n != 'id'