changeset 08d07aa63e73 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=08d07aa63e73
description:
Add backend documentation
issue9134
review269041003
diffstat:
doc/ref/backend.rst | 318 +++++++++++++++++++++++++++++++++
doc/ref/index.rst | 1 +
doc/ref/models.rst | 2 +-
trytond/backend/database.py | 115 +-----------
trytond/backend/postgresql/database.py | 5 +-
trytond/backend/postgresql/table.py | 20 +-
trytond/backend/sqlite/database.py | 5 +-
trytond/backend/sqlite/table.py | 22 +-
trytond/backend/table.py | 128 +------------
trytond/ir/action.py | 2 -
10 files changed, 358 insertions(+), 260 deletions(-)
diffs (953 lines):
diff -r 2f01695e906a -r 08d07aa63e73 doc/ref/backend.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ref/backend.rst Thu Sep 08 13:05:06 2022 +0200
@@ -0,0 +1,318 @@
+.. _ref-backend:
+.. module:: trytond.backend
+
+=======
+Backend
+=======
+
+The backend manages the database connection and schema manipulation.
+
+.. attribute:: name
+
+ The name of the backend configured.
+
+.. class:: Database(name)
+
+ Manage the connection to the named database.
+
+.. method:: Database.connect()
+
+ Connect to the database and return the instance.
+
+.. method:: Database.get_connection([autocommit[, readonly]])
+
+ Retrieve a connection object as defined by :pep:249#connection.
+ If autocommit is set, the connection is committed after each statement.
+ If readonly is set, the connection is read only.
+
+.. method:: Database.put_connection(connection[, close])
+
+ Release the connection.
+ If close is set, the connection is discarded.
+
+.. method:: Database.close()
+
+ Close all connections.
+
+.. classmethod:: Database.create(connection, database_name)
+
+ Create the named database using the connection.
+
+.. classmethod:: Database.drop(connection, database_name)
+
+ Drop the named database using the connection.
+
+.. method:: Database.list([hostname])
+
+ Return a list of Tryton database names.
+ ``hostname`` filters the databases with the same configured hostname.
+
+.. method:: Database.init()
+
+ Initialize the database schema.
+
+.. method:: Database.test([hostname])
+
+ Return if the database is a Tryton database.
+ If ``hostname`` is set, it checks also if it has the same configured
+ hostname.
+
+.. method:: Database.nextid(connection, table)
+
+ Return the next ID for the ``table`` using the ``connection``.
+
+ .. note:: It may return ``None`` for some database.
+
+.. method:: Database.setnextid(connection, table, value)
+
+ Set the ``value`` as current ID to the ``table`` using the ``connection``.
+
+.. method:: Database.currid(connection, table)
+
+ Return the current ID of the ``table`` using the ``connection``.
+
+.. classmethod:: Database.lock(connection, table)
+
+ Lock the ``table`` using the ``connection``.
+
+.. method:: Database.lock_id(id[, timeout])
+
+ Return the SQL expression to lock the ``id``.
+ Set ``timeout`` to wait for the lock.
+
+.. method:: Database.has_constraint(constraint)
+
+ Return if the database handle the ``constraint``.
+
+.. method:: Database.has_returning()
+
+ Return if the database supports ``RETURNING`` in ``INSERT`` and ``UPDATE``.
+
+.. method:: Database.has_multirow_insert()
+
+ Return if the database supports ``INSERT`` of multi-rows.
+
+.. method:: Database.has_select_for()
+
+ Return if the database supports ``FOR UPDATE`` and ``FOR SHARE`` in
+ ``SELECT``.
+
+.. method:: Database.get_select_for_skip_locked()
+
+ Return For class with skip locked.
+
+.. method:: Database.has_window_functions()
+
+ Return if the database supports window functions.
+
+.. method:: Database.has_unaccent()
+
+ Return if the database suppport unaccentuated function.
+
+.. method:: Database.unaccent(value)
+
+ Return the SQL expression of unaccentuated ``value``.
+
+.. method:: Database.has_similarity()
+
+ Return if the database suppports similarity function.
+
+.. method:: Database.similarity(column, value)
+
+ Return the SQL expression that compare the similarity of ``column`` and
+ ``value``.
+
+.. method:: Database.has_search_full_text()
+
+ Return if the database suppports full text search.
+
+.. method:: Database.format_full_text(\*documents[, language])
+
+ Return the SQL expression that format the ``documents`` into text search
+ vectors for the ``language``.
+
+ The order of ``documents`` define the weight for proximity ranking.
+
+.. method:: Database.format_full_text_query(query[, language])
+
+ Convert the ``query`` expression into full text query.
+
+.. method:: Database.search_full_text(document, query)
+
+ Return the SQL expression for searching ``document`` with the ``query``.
+
+.. method:: Database.rank_full_text(document, query[, normalize])
+
+ Return the SQL expression to rank ``document`` with the ``query``.
+
+.. classmethod:: Database.has_sequence()
+
+ Return if the database supports sequence querying and assignation.
+
+.. method:: Database.sequence_exist(connection, name)
+
+ Return if the named sequence exists using the ``connection``.
+
+.. method:: Database.sequence_create(connection, name[, number_increment[,
start_value]])
+
+ Create a named sequence incremented by ``number_increment`` or ``1`` and
+ starting at ``start_value`` or ``1`` using the ``connection``.
+
+.. method:: Database.sequence_update(connection, name[, number_increment[,
start_value]])
+
+ Modify the named sequence with ``number_increment`` and ``start_value``using
+ the ``connection``.
+
+.. method:: Database.sequence_rename(connection, old_name, new_name)
+
+ Rename the sequece from ``old_name`` to ``new_name`` using the
+ ``connection``.
+
+.. method:: Database.sequence_delete(connection, name)
+
+ Delete the named sequence using the ``connection``.
+
+.. method:: Database.sequence_next_number(connection, name)
+
+ Return the next number fo the named sequence using the ``connection``.
+
+.. method:: Database.has_channel(connection, name)
+
+ Return if the database supports ``LISTEN`` and ``NOTIFY`` on channel.
+
+.. method:: Database.sql_type(type_)
+
+ Return the namedtuple('SQLType', 'base type') corresponding to the SQL
+ ``type_``.
+
+.. method:: Database.sql_format(type_, value)
+
+ Return the ``value`` casted for the SQL ``type_``.
+
+.. method:: Database.json_get(column[, key])
+
+ Return the JSON value of the JSON ``key`` from the ``column``.
+
+.. method:: Database.json_key_exists(column, key)
+
+ Return the SQL expression to test if ``key`` exists in the JSON ``column``.
+
+.. method:: Database.json_any_keys_exist(column, keys)
+
+ Return the SQL expression to test if any ``keys`` exist in the JSON
+ ``column``.
+
+.. method:: Database.json_all_keys_exist(column, keys)
+
+ Return the SQL expression to test if all ``keys`` exist in the JSON
+ ``column``.
+
+.. method:: Database.json_contains(column, json)
+
+ Rteurn the SQL expression to test if the JSON ``column`` contains ``json``.
+
+.. class:: TableHandler(model[, history])
+
+ Handle table for the ``model``.
+ If ``history`` is set, the table is the one storing the history.
+
+.. attribute:: TableHandler.namedatalen
+
+ The maximing length of named data for the database.
+
+.. classmethod:: TableHandler.table_exist(table_name)
+
+ Return if the named table exists.
+
+.. classmethod:: TableHandler.table_rename(old_name, new_name)
+
+ Rename the table from ``old_name`` to ``new_name``.
+
+.. method:: TableHandler.column_exist(column_name)
+
+ Return if the named column exists.
+
+.. method:: TableHandler.column_rename(old_name, new_name)
+
+ Rename the column from ``old_name`` to ``new_name``.
+
+.. method:: TableHandler.alter_size(column_name, column_type)
+
+ Modify the size of the named column using the column type.
+
+.. method:: TableHandler.alter_type(column_name, column_type)
+
+ Modify the type of the named column.
+
+.. method:: TableHandler.column_is_type(column_name, type_[, size])
+
+ Return if the column is of type ``type_``.
+ If ``type`` is ``VARCHAR``, ``size`` is also compared except if the value if
+ negative.
+
+.. method:: TableHandler.db_default(column_name, value)
+
+ Set the default ``value`` on the named column.
+
+.. method:: TableHandler.add_column(column_name, abstract_type[, default[,
comment]])
+
+ Add the named column of abstract type.
+ The ``default`` is a method that return the value to fill the new column.
+ ``comment`` set as comment for the column.
+
+.. method:: TableHandler.add_fk(column_name, reference[, on_delete])
+
+ Add a foreign key constraint on the named column to target the ``reference``
+ table name.
+ ``on_delete`` defines the method to use when foreign record is deleted.
+
+.. method:: TableHandler.drop_fk(column_name[, table])
+
+ Drop the foreign key constrant on the named column.
+ ``table`` can be used to alter another table.
+
+.. method:: TableHandler.index_action(columns[, action[, where[, table]]])
+
+ Add or remove index on listed ``columns``.
+ ``where`` is an optional SQL expression for partial index.
+ ``table`` can be used to alter another table.
+
+.. method:: TableHandler.not_null_action(column_name[, action])
+
+ Add or remove ``NOT NULL`` on the named column.
+
+.. method:: TableHandler.add_constraint(ident, constraint)
+
+ Add the SQL expression ``constraint`` as constraint named ``ident`` on the
+ table.
+
+.. method:: TableHandler.drop_constraint(ident[, table])
+
+ Drop the named ``ident`` constraint.
+ ``table`` can be used to alter another table.
+
+.. method:: TableHandler.drop_column(column_name)
+
+ Drop the named column.
+
+.. classmethod:: TableHandler.drop_table(model, table[, cascade])
+
+ Drop the named ``table`` and clean ``ir.model.data`` from the given
+ ``model``.
+ Set ``cascade`` to drop objects that depend on the table.
+
+.. classmethod:: TableHandler.convert_name(name)
+
+ Convert the data name to be lower than namedatalen.
+
+.. exception:: DatabaseIntegrityError
+
+ Exception raised when the relational integrity of the database is affected.
+
+.. exception:: DatabaseDataError
+
+ Exception raised for errors that are due to problems with the processed
data.
+
+.. exception:: DatabaseOperationalError
+
+ Exception raised for errors that are related to the database’s operation.
diff -r 2f01695e906a -r 08d07aa63e73 doc/ref/index.rst
--- a/doc/ref/index.rst Thu Sep 01 22:10:10 2022 +0200
+++ b/doc/ref/index.rst Thu Sep 08 13:05:06 2022 +0200
@@ -15,6 +15,7 @@
pyson
transaction
exceptions
+ backend
tools/index
pool
rpc
diff -r 2f01695e906a -r 08d07aa63e73 doc/ref/models.rst
--- a/doc/ref/models.rst Thu Sep 01 22:10:10 2022 +0200
+++ b/doc/ref/models.rst Thu Sep 08 13:05:06 2022 +0200
@@ -538,7 +538,7 @@
.. classmethod:: ModelSQL.__table_handler__([module_name[, history]])
- Return a TableHandler for the Model.
+ Return a :class:`~trytond.backend.TableHandler` instance for the Model.
.. classmethod:: ModelSQL.table_query()
diff -r 2f01695e906a -r 08d07aa63e73 trytond/backend/database.py
--- a/trytond/backend/database.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/backend/database.py Thu Sep 08 13:05:06 2022 +0200
@@ -24,65 +24,29 @@
self.name = name
def connect(self):
- '''
- Connect to the database
-
- :return: the database
- '''
raise NotImplementedError
- def get_connection(self, autocommit, readonly=False):
- '''Retrieve a connection on the database
-
- :param autocommit: a boolean to activate autocommit
- :param readonly: a boolean to specify if the transaction is readonly
- '''
+ def get_connection(self, autocommit=False, readonly=False):
raise NotImplementedError
def put_connection(self, connection, close=False):
- '''Release the connection
-
- :param close: if close is True the connection is discarded
- '''
raise NotImplementedError
def close(self):
- '''
- Close all connection
- '''
raise NotImplementedError
@classmethod
def create(cls, connection, database_name):
- '''
- Create a database
-
- :param connection: the connection to the database
- :param database_name: the new database name
- '''
raise NotImplementedError
- def drop(self, connection, database_name):
- '''
- Drop a database
-
- :param connection: the connection to the database
- :param database_name: the database name
- '''
+ @classmethod
+ def drop(cls, connection, database_name):
raise NotImplementedError
def list(self, hostname=None):
- '''
- Get the list of database
-
- :return: a list of database name
- '''
raise NotImplementedError
def init(self):
- '''
- Initialize a database
- '''
raise NotImplementedError
def test(self, hostname=None):
@@ -92,105 +56,52 @@
raise NotImplementedError
def nextid(self, connection, table):
- '''
- Return the next sequenced id for a table.
-
- :param connection: a connection on the database
- :param table: the table name
- :return: an integer
- '''
+ pass
def setnextid(self, connection, table, value):
- '''
- Set the current sequenced id for a table.
-
- :param connection: a connection on the database
- :param table: the table name
- '''
+ pass
def currid(self, connection, table):
- '''
- Return the current sequenced id for a table.
-
- :param connection: a connection on the database
- :param table: the table name
- :return: an integer
- '''
-
- def update_auto_increment(self, connection, table, value):
- '''
- Update auto_increment value of table
-
- :param connection: a connection on the database
- :param table: the table name
- :param value: the auto_increment value
- '''
pass
@classmethod
def lock(cls, connection, table):
- '''
- Lock the table
-
- :param connection: a connection on the database
- :param table: the table name
- '''
raise NotImplementedError
def lock_id(self, id, timeout=None):
- """Return SQL function to lock resource"""
raise NotImplementedError
def has_constraint(self, constraint):
- '''
- Return True if database handle constraint.
-
- :return: a boolean
- '''
raise NotImplementedError
def has_returning(self):
- '''
- Return True if database implements RETURNING clause in INSERT or UPDATE
- statements.
-
- :return: a boolean
- '''
return False
def has_multirow_insert(self):
- 'Return True if database supports multirow insert'
return False
def has_select_for(self):
- "Return if database supports FOR UPDATE/SHARE clause in SELECT."
return False
def get_select_for_skip_locked(self):
- "Return For class with skip locked"
return For
def has_window_functions(self):
- "Return if database supports window functions."
return False
def has_unaccent(self):
- "Return if database supports unaccentuated searches"
return False
def unaccent(self, value):
- "Return the expression to use for unaccentuated columns"
return value
def has_similarity(self):
- "Return if database supports similarity"
return False
def similarity(self, column, value):
raise NotImplementedError
def has_search_full_text(self):
- "Return if database supports full text search"
return False
def format_full_text(self, *documents, language=None):
@@ -200,7 +111,6 @@
raise NotImplementedError
def search_full_text(self, document, query):
- "Return the clause expression for searching document against query"
raise NotImplementedError
def rank_full_text(self, document, query, normalize=None):
@@ -209,75 +119,60 @@
@classmethod
def has_sequence(cls):
- "Return if database supports sequence querying and assignation"
return False
def sequence_exist(self, connection, name):
- "Return if a sequence exists"
if not self.has_sequence():
return
raise NotImplementedError
def sequence_create(
self, connection, name, number_increment=1, start_value=1):
- "Creates a sequence"
if not self.has_sequence():
return
raise NotImplementedError
def sequence_update(
self, connection, name, number_increment=1, start_value=1):
- "Modifies a sequence"
if not self.has_sequence():
return
raise NotImplementedError
def sequence_rename(self, connection, old_name, new_name):
- "Renames a sequence"
if not self.has_sequence():
return
raise NotImplementedError
def sequence_delete(self, connection, name):
- "Removes a sequence"
if not self.has_sequence():
return
raise NotImplementedError
def sequence_next_number(self, connection, name):
- "Gets the next number of a sequence"
if not self.has_sequence():
return
raise NotImplementedError
def has_channel(self):
- "Return True if database supports LISTEN/NOTIFY channel"
return False
def sql_type(self, type_):
- 'Return the SQLType tuple corresponding to the SQL type'
pass
def sql_format(self, type_, value):
- 'Return value correctly casted into type_'
pass
def json_get(self, column, key=None):
- "Return the JSON value of the JSON key"
raise NotImplementedError
def json_key_exists(self, column, key):
- "Return expression for key exists in JSON column"
raise NotImplementedError
def json_any_keys_exist(self, column, keys):
- "Return expression for any keys exist in JSON column"
raise NotImplementedError
def json_all_keys_exist(self, column, keys):
- "Rteurn expression for all keys exist in JSON column"
raise NotImplementedError
def json_contains(self, column, json):
- "Return expression for column contains JSON"
raise NotImplementedError
diff -r 2f01695e906a -r 08d07aa63e73 trytond/backend/postgresql/database.py
--- a/trytond/backend/postgresql/database.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/backend/postgresql/database.py Thu Sep 08 13:05:06 2022 +0200
@@ -293,11 +293,12 @@
connection.commit()
cls._list_cache.clear()
- def drop(self, connection, database_name):
+ @classmethod
+ def drop(cls, connection, database_name):
cursor = connection.cursor()
cursor.execute(SQL("DROP DATABASE {}")
.format(Identifier(database_name)))
- self.__class__._list_cache.clear()
+ cls._list_cache.clear()
def get_version(self, connection):
version = connection.server_version
diff -r 2f01695e906a -r 08d07aa63e73 trytond/backend/postgresql/table.py
--- a/trytond/backend/postgresql/table.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/backend/postgresql/table.py Thu Sep 08 13:05:06 2022 +0200
@@ -94,19 +94,19 @@
(self.sequence_name,))
self._update_definitions(columns=True)
- @staticmethod
- def table_exist(table_name):
+ @classmethod
+ def table_exist(cls, table_name):
transaction = Transaction()
return bool(transaction.database.get_table_schema(
transaction.connection, table_name))
- @staticmethod
- def table_rename(old_name, new_name):
+ @classmethod
+ def table_rename(cls, old_name, new_name):
transaction = Transaction()
cursor = transaction.connection.cursor()
# Rename table
- if (TableHandler.table_exist(old_name)
- and not TableHandler.table_exist(new_name)):
+ if (cls.table_exist(old_name)
+ and not cls.table_exist(new_name)):
cursor.execute(SQL('ALTER TABLE {} RENAME TO {}').format(
Identifier(old_name), Identifier(new_name)))
# Rename sequence
@@ -117,8 +117,8 @@
# Rename history table
old_history = old_name + "__history"
new_history = new_name + "__history"
- if (TableHandler.table_exist(old_history)
- and not TableHandler.table_exist(new_history)):
+ if (cls.table_exist(old_history)
+ and not cls.table_exist(new_history)):
cursor.execute('ALTER TABLE "%s" RENAME TO "%s"'
% (old_history, new_history))
@@ -520,8 +520,8 @@
Identifier(column_name)))
self._update_definitions(columns=True)
- @staticmethod
- def drop_table(model, table, cascade=False):
+ @classmethod
+ def drop_table(cls, model, table, cascade=False):
cursor = Transaction().connection.cursor()
cursor.execute('DELETE FROM ir_model_data WHERE model = %s', (model,))
diff -r 2f01695e906a -r 08d07aa63e73 trytond/backend/sqlite/database.py
--- a/trytond/backend/sqlite/database.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/backend/sqlite/database.py Thu Sep 08 13:05:06 2022 +0200
@@ -475,9 +475,10 @@
cursor = conn.cursor()
cursor.close()
- def drop(self, connection, database_name):
+ @classmethod
+ def drop(cls, connection, database_name):
if database_name == ':memory:':
- self._local.memory_database._conn = None
+ cls._local.memory_database._conn = None
return
if os.sep in database_name:
return
diff -r 2f01695e906a -r 08d07aa63e73 trytond/backend/sqlite/table.py
--- a/trytond/backend/sqlite/table.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/backend/sqlite/table.py Thu Sep 08 13:05:06 2022 +0200
@@ -44,8 +44,8 @@
self._update_definitions()
- @staticmethod
- def table_exist(table_name):
+ @classmethod
+ def table_exist(cls, table_name):
cursor = Transaction().connection.cursor()
cursor.execute("SELECT sql FROM sqlite_master "
"WHERE type = 'table' AND name = ?",
@@ -80,18 +80,18 @@
cursor.execute('DROP TABLE "_temp_%s"' % table_name)
return True
- @staticmethod
- def table_rename(old_name, new_name):
+ @classmethod
+ def table_rename(cls, old_name, new_name):
cursor = Transaction().connection.cursor()
- if (TableHandler.table_exist(old_name)
- and not TableHandler.table_exist(new_name)):
+ if (cls.table_exist(old_name)
+ and not cls.table_exist(new_name)):
cursor.execute('ALTER TABLE %s RENAME TO %s'
% (_escape_identifier(old_name), _escape_identifier(new_name)))
# Rename history table
old_history = old_name + "__history"
new_history = new_name + "__history"
- if (TableHandler.table_exist(old_history)
- and not TableHandler.table_exist(new_history)):
+ if (cls.table_exist(old_history)
+ and not cls.table_exist(new_history)):
cursor.execute('ALTER TABLE %s RENAME TO %s'
% (_escape_identifier(old_history),
_escape_identifier(new_history)))
@@ -109,7 +109,7 @@
cursor = transaction.connection.cursor()
temp_table = '__temp_%s' % self.table_name
temp_columns = dict(self._columns)
- TableHandler.table_rename(self.table_name, temp_table)
+ self.table_rename(self.table_name, temp_table)
self._init(self._model, history=self.history)
columns, old_columns = [], []
for name, values in temp_columns.items():
@@ -368,8 +368,8 @@
else:
self._recreate_table(drop_columns=[column_name])
- @staticmethod
- def drop_table(model, table, cascade=False):
+ @classmethod
+ def drop_table(cls, model, table, cascade=False):
cursor = Transaction().connection.cursor()
cursor.execute('DELETE from ir_model_data where model = ?',
(model,))
diff -r 2f01695e906a -r 08d07aa63e73 trytond/backend/table.py
--- a/trytond/backend/table.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/backend/table.py Thu Sep 08 13:05:06 2022 +0200
@@ -40,178 +40,62 @@
self.sequence_name = self.table_name + '_id_seq'
self.history = history
- @staticmethod
- def table_exist(table_name):
- '''
- Table exist
-
- :param table_name: the table name
- :return: a boolean
- '''
+ @classmethod
+ def table_exist(cls, table_name):
raise NotImplementedError
- @staticmethod
- def table_rename(old_name, new_name):
- '''
- Rename table
-
- :param old_name: the old table name
- :param new_name: the new table name
- '''
+ @classmethod
+ def table_rename(cls, old_name, new_name):
raise NotImplementedError
def column_exist(self, column_name):
- '''
- Column exist
-
- :param column_name: the column name
- :return: a boolean
- '''
raise NotImplementedError
def column_rename(self, old_name, new_name):
- '''
- Rename column if exists
-
- :param old_name: the name of the existing column
- :param new_name: the new name of the column
- '''
raise NotImplementedError
def alter_size(self, column_name, column_type):
- '''
- Modify size of a column
-
- :param column_name: the column name
- :param column_type: the column definition
- '''
raise NotImplementedError
def alter_type(self, column_name, column_type):
- '''
- Modify type of a column
-
- :param column_name: the column name
- :param column_type: the column definition
- '''
raise NotImplementedError
def column_is_type(self, column_name, type_, *, size=-1):
- '''
- Return True if the column is of type type_
-
- :param column_name: the column name
- :param type_: the generic name of the type
- :param size: if `type` is VARCHAR you can specify its size.
- Use a negative value to ignore the size check.
- Defaults to -1
- :return: a boolean
- '''
raise NotImplementedError
def db_default(self, column_name, value):
- '''
- Set a default on a column
-
- :param column_name: the column name
- :param value: the default value
- '''
raise NotImplementedError
def add_column(self, column_name, abstract_type, default=None, comment=''):
- '''
- Add a column
-
- :param column_name: the column name
- :param abstract_type: the abstract type that will represent this column
- :param default: the method that return default value to use
- :param comment: An optional comment on the column
- '''
raise NotImplementedError
def add_fk(self, column_name, reference, on_delete=None):
- '''
- Add a foreign key
-
- :param column_name: the column name
- :param reference: the foreign table name
- :param on_delete: the "on delete" value
- '''
raise NotImplementedError
def drop_fk(self, column_name, table=None):
- '''
- Drop a foreign key
-
- :param column_name: the column name
- :param table: optional table name
- '''
raise NotImplementedError
def index_action(self, columns, action='add', where=None, table=None):
- '''
- Add/remove an index
-
- :param columns: the column or a list of columns/expressions
- :param action: 'add' or 'remove'
- :param where: predicate expression
- :param table: optional table name
- '''
raise NotImplementedError
def not_null_action(self, column_name, action='add'):
- '''
- Add/remove a "not null"
-
- :param column_name: the column name
- :param action: 'add' or 'remove'
- '''
raise NotImplementedError
def add_constraint(self, ident, constraint):
- '''
- Add a constraint
-
- :param ident: the name of the constraint
- :param constraint: the definition of the constraint
- '''
raise NotImplementedError
def drop_constraint(self, ident, table=None):
- '''
- Remove a constraint
-
- :param ident: the name of the constraint
- :param table: optional table name
- '''
raise NotImplementedError
def drop_column(self, column_name):
- '''
- Remove a column
-
- :param column_name: the column name
- '''
raise NotImplementedError
- @staticmethod
- def drop_table(model, table, cascade=False):
- '''
- Remove a table and clean ir_model_data from the given model.
-
- :param model: the model name
- :param table: the table name
- :param cascade: a boolean to add "CASCADE" to the delete query
- '''
+ @classmethod
+ def drop_table(cls, model, table, cascade=False):
raise NotImplementedError
@classmethod
def convert_name(cls, name):
- '''
- Convert data name in respect of namedatalen.
-
- :param name: the data name
- '''
if cls.namedatalen and len(name) >= cls.namedatalen:
if isinstance(name, str):
name = name.encode('utf-8')
diff -r 2f01695e906a -r 08d07aa63e73 trytond/ir/action.py
--- a/trytond/ir/action.py Thu Sep 01 22:10:10 2022 +0200
+++ b/trytond/ir/action.py Thu Sep 08 13:05:06 2022 +0200
@@ -398,8 +398,6 @@
cursor.execute(*ir_action.update(
[ir_action.id], [action.id],
where=ir_action.id == record.id))
- transaction.database.update_auto_increment(
- transaction.connection, cls._table, action.id)
record = cls(action.id)
new_records.append(record)
to_write.extend(([record], later))