From a13bf7246f1045a2d31f2317c55cbe2d4edf91d1 Mon Sep 17 00:00:00 2001 From: sokumon Date: Wed, 30 Jul 2025 19:57:51 +0530 Subject: [PATCH 1/3] fix: prevent row-size limit error --- frappe/database/schema.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frappe/database/schema.py b/frappe/database/schema.py index cb0afb4281..40702427d0 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -436,6 +436,8 @@ def get_definition(fieldtype, precision=None, length=None, *, options=None): if length: if coltype == "varchar": + if length < 64: + length = 64 size = length elif coltype == "int" and length < 11: # allow setting custom length for int if length provided is less than 11 @@ -470,5 +472,9 @@ def add_column(doctype, column_name, fieldtype, precision=None, length=None, def query += " not null" if default: query += f" default '{default}'" - - frappe.db.sql(query) + try: + frappe.db.sql(query) + except Exception as err: + # 1118 is error code for the row size limit exceeded error + if hasattr(err, "args") and err.args[0] == 1118: + frappe.db.rollback() From 3cb061bacb212c11c4408549405e38d2b1e7e36a Mon Sep 17 00:00:00 2001 From: sokumon Date: Mon, 4 Aug 2025 19:32:34 +0530 Subject: [PATCH 2/3] fix: add reference and test_case --- frappe/database/schema.py | 9 +++------ frappe/tests/test_db_update.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 40702427d0..a3d1d83a0b 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -436,6 +436,7 @@ def get_definition(fieldtype, precision=None, length=None, *, options=None): if length: if coltype == "varchar": + # Reference: https://mariadb.com/docs/server/server-usage/storage-engines/innodb/innodb-row-formats/troubleshooting-row-size-too-large-errors-with-innodb if length < 64: length = 64 size = length @@ -472,9 +473,5 @@ def add_column(doctype, column_name, fieldtype, precision=None, length=None, def query += " not null" if default: query += f" default '{default}'" - try: - frappe.db.sql(query) - except Exception as err: - # 1118 is error code for the row size limit exceeded error - if hasattr(err, "args") and err.args[0] == 1118: - frappe.db.rollback() + + frappe.db.sql(query) diff --git a/frappe/tests/test_db_update.py b/frappe/tests/test_db_update.py index dc150b1be8..dd9a985ba6 100644 --- a/frappe/tests/test_db_update.py +++ b/frappe/tests/test_db_update.py @@ -176,6 +176,20 @@ class TestDBUpdate(IntegrationTestCase): self.assertEqual(frappe.db.get_column_type(referring_doctype.name, link), "uuid") + @run_only_if(db_type_is.MARIADB) + def test_row_size(self): + from frappe.database.schema import add_column + from frappe.utils import get_table_name + + test_doc = new_doctype().insert() + try: + for i in range(400): + add_column(test_doc.name, fieldtype="Data", column_name=f"col{i}", length=63) + except Exception as e: + print(e) + finally: + frappe.db.sql_ddl(f"drop table `{get_table_name(test_doc.name)}`") + class TestDBUpdateSanityChecks(IntegrationTestCase): @run_only_if(db_type_is.MARIADB) From 6f9c7f3241890fe809e721a8bd28b57f00ae55f2 Mon Sep 17 00:00:00 2001 From: sokumon Date: Wed, 1 Oct 2025 17:43:39 +0530 Subject: [PATCH 3/3] fix: add a correct test --- frappe/tests/test_db_update.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/frappe/tests/test_db_update.py b/frappe/tests/test_db_update.py index dd9a985ba6..ec2cb423b7 100644 --- a/frappe/tests/test_db_update.py +++ b/frappe/tests/test_db_update.py @@ -177,18 +177,16 @@ class TestDBUpdate(IntegrationTestCase): self.assertEqual(frappe.db.get_column_type(referring_doctype.name, link), "uuid") @run_only_if(db_type_is.MARIADB) - def test_row_size(self): + def test_varchar_length(self): from frappe.database.schema import add_column - from frappe.utils import get_table_name test_doc = new_doctype().insert() - try: - for i in range(400): - add_column(test_doc.name, fieldtype="Data", column_name=f"col{i}", length=63) - except Exception as e: - print(e) - finally: - frappe.db.sql_ddl(f"drop table `{get_table_name(test_doc.name)}`") + col_name = f"col_{frappe.generate_hash(length=4)}" + add_column(test_doc.name, fieldtype="Data", column_name=col_name, length=50) + length = frappe.db.sql( + f"SELECT CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tab{test_doc.name}' AND COLUMN_NAME = '{col_name}' ", + )[0][0] + self.assertEqual(length, 64) class TestDBUpdateSanityChecks(IntegrationTestCase):