From d8c3e5cccaf5fc16d91a5dd1426a4c24c131066c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 8 Nov 2021 19:31:34 +0100 Subject: [PATCH] Use RENAME and DROP COLUMN with SQLite backend issue7703 review367691002 --- CHANGELOG | 1 + trytond/backend/sqlite/table.py | 60 +++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c9202a0da4..92ac0cfe34 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Use RENAME and DROP COLUMN with SQLite backend * Support window functions with SQLite backend * Use JSONB to store Dict field on PostgreSQL backend diff --git a/trytond/backend/sqlite/table.py b/trytond/backend/sqlite/table.py index 5ad301daa4..ac151fa3fb 100644 --- a/trytond/backend/sqlite/table.py +++ b/trytond/backend/sqlite/table.py @@ -7,6 +7,8 @@ import logging import re import warnings +from .database import sqlite + __all__ = ['TableHandler'] logger = logging.getLogger(__name__) @@ -124,9 +126,17 @@ class TableHandler(TableHandlerInterface): self._update_definitions() def column_rename(self, old_name, new_name): + cursor = Transaction().connection.cursor() if self.column_exist(old_name): if not self.column_exist(new_name): - self._recreate_table({old_name: {'name': new_name}}) + if sqlite.sqlite_version_info >= (3, 25, 0): + cursor.execute('ALTER TABLE %s RENAME COLUMN %s TO %s' % ( + _escape_identifier(self.table_name), + _escape_identifier(old_name), + _escape_identifier(new_name))) + self._update_definitions(columns=True) + else: + self._recreate_table({old_name: {'name': new_name}}) else: logger.warning( 'Unable to rename column %s on table %s to %s.', @@ -346,27 +356,33 @@ class TableHandler(TableHandlerInterface): transaction = Transaction() database = transaction.database cursor = transaction.connection.cursor() - temp_table = '__temp_%s' % self.table_name - TableHandler.table_rename(self.table_name, temp_table) - new_table = TableHandler(self._model, history=self.history) - for name, values in self._columns.items(): - if name != column_name: - typname = values['typname'] - size = values['size'] - new_table._add_raw_column( - name, database.sql_type(typname), field_size=size) - columns_name = list(new_table._columns.keys()) - cursor.execute( - ('INSERT INTO %s (' - + ','.join(str(_escape_identifier(c)) - for c in columns_name) - + ') SELECT ' - + ','.join(_escape_identifier(c) for c in columns_name) - + ' FROM %s') - % (_escape_identifier(self.table_name), - _escape_identifier(temp_table))) - cursor.execute('DROP TABLE %s' % _escape_identifier(temp_table)) - self._update_definitions() + if sqlite.sqlite_version_info >= (3, 25, 0): + cursor.execute('ALTER TABLE %s DROP COLUMN %s' % ( + _escape_identifier(self.table_name), + _escape_identifier(column_name))) + self._update_definitions(columns=True) + else: + temp_table = '__temp_%s' % self.table_name + TableHandler.table_rename(self.table_name, temp_table) + new_table = TableHandler(self._model, history=self.history) + for name, values in self._columns.items(): + if name != column_name: + typname = values['typname'] + size = values['size'] + new_table._add_raw_column( + name, database.sql_type(typname), field_size=size) + columns_name = list(new_table._columns.keys()) + cursor.execute( + ('INSERT INTO %s (' + + ','.join(str(_escape_identifier(c)) + for c in columns_name) + + ') SELECT ' + + ','.join(_escape_identifier(c) for c in columns_name) + + ' FROM %s') + % (_escape_identifier(self.table_name), + _escape_identifier(temp_table))) + cursor.execute('DROP TABLE %s' % _escape_identifier(temp_table)) + self._update_definitions() @staticmethod def drop_table(model, table, cascade=False):