diff --git a/odoo/addons/base/data/base_data.sql b/odoo/addons/base/data/base_data.sql index b90c3bbb779..a40dc963ce7 100644 --- a/odoo/addons/base/data/base_data.sql +++ b/odoo/addons/base/data/base_data.sql @@ -14,14 +14,14 @@ CREATE TABLE ir_act_client (primary key(id)) INHERITS (ir_actions); CREATE TABLE res_users ( id serial NOT NULL, - active boolean default True, - login varchar(64) NOT NULL UNIQUE, - password varchar default null, -- No FK references below, will be added later by ORM -- (when the destination rows exist) company_id integer, -- references res_company, partner_id integer, -- references res_partner, + active boolean default True, create_date timestamp without time zone, + login varchar(64) NOT NULL UNIQUE, + password varchar default null, primary key(id) ); @@ -86,11 +86,11 @@ CREATE TABLE ir_model_data ( create_date timestamp without time zone DEFAULT (now() at time zone 'UTC'), write_date timestamp without time zone DEFAULT (now() at time zone 'UTC'), write_uid integer, + res_id integer, noupdate boolean DEFAULT False, name varchar NOT NULL, module varchar NOT NULL, model varchar NOT NULL, - res_id integer, primary key(id) ); @@ -113,9 +113,9 @@ CREATE TABLE res_company ( CREATE TABLE res_partner ( id serial, - name varchar, company_id integer, create_date timestamp without time zone, + name varchar, primary key(id) ); diff --git a/odoo/fields.py b/odoo/fields.py index 45c959ecbc6..3c73428c535 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -21,7 +21,7 @@ import pytz from .tools import ( float_repr, float_round, float_compare, float_is_zero, html_sanitize, human_size, pg_varchar, ustr, OrderedSet, pycompat, sql, date_utils, unique, - image_process, merge_sequences, + image_process, merge_sequences, SQL_ORDER_BY_TYPE, ) from .tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT from .tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT @@ -937,6 +937,11 @@ class Field(MetaField('DummyField', (object,), {})): # Update database schema # + @property + def column_order(self): + """ Prescribed column order in table. """ + return 0 if self.column_type is None else SQL_ORDER_BY_TYPE[self.column_type[0]] + def update_db(self, model, columns): """ Update the database schema to implement this field. diff --git a/odoo/models.py b/odoo/models.py index 2ba025553f5..0c01392b208 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2850,9 +2850,9 @@ class BaseModel(metaclass=MetaModel): return field.column_type[1] + (" NOT NULL" if field.required else "") tools.create_model_table(cr, self._table, self._description, [ - (name, make_type(field), field.string) - for name, field in self._fields.items() - if name != 'id' and field.store and field.column_type + (field.name, make_type(field), field.string) + for field in sorted(self._fields.values(), key=lambda f: f.column_order) + if field.name != 'id' and field.store and field.column_type ]) if self._parent_store: @@ -2868,7 +2868,7 @@ class BaseModel(metaclass=MetaModel): columns = tools.table_columns(cr, self._table) fields_to_compute = [] - for field in self._fields.values(): + for field in sorted(self._fields.values(), key=lambda f: f.column_order): if not field.store: continue if field.manual and not update_custom_fields: diff --git a/odoo/tools/sql.py b/odoo/tools/sql.py index 8cbf8c883da..914cdd3bed0 100644 --- a/odoo/tools/sql.py +++ b/odoo/tools/sql.py @@ -6,6 +6,7 @@ import logging import psycopg2 import odoo.sql_db +from collections import defaultdict from contextlib import closing _schema = logging.getLogger('odoo.schema') @@ -50,6 +51,17 @@ def table_kind(cr, tablename): cr.execute(query, (tablename,)) return cr.fetchone()[0] if cr.rowcount else None +# prescribed column order by type size: 4 bytes, 1 byte, 8 bytes, variable size +# (values have been chosen to minimize padding in rows; unknown column types +# are considered variable size and put last) +SQL_ORDER_BY_TYPE = defaultdict(lambda: 6, { + 'int4': 1, # 4 bytes + 'date': 2, # 4 bytes + 'bool': 3, # 1 byte + 'float8': 4, # 8 bytes + 'timestamp': 5, # 8 bytes +}) + def create_model_table(cr, tablename, comment=None, columns=()): """ Create the table for a model. """ colspecs = ['id SERIAL NOT NULL'] + [