Bug #120326 Upgrade fails on partitioned tables due to stale THD error from stored procedure compilation
Submitted: 22 Apr 19:32 Modified: 23 Apr 6:17
Reporter: Shiv Bhatt Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Data Dictionary Severity:S2 (Serious)
Version:8.4 OS:Any
Assigned to: CPU Architecture:Any
Tags: check_table_functions, partition, stored procedure, upgrade

[22 Apr 19:32] Shiv Bhatt
Description:
Upgrading from MySQL 8.0.40 to 8.4.7 fails with MY-014078 on a valid partitioned table when a stored procedure containing ENGINE=Memory exists on the instance.

During the upgrade, do_server_upgrade_checks runs two phases:
1. check_routines - compiles all stored procedures to validate them
2. check_table_funs - opens all tables with SQL functions in their definitions

In check_routines, if a stored procedure body contains CREATE TEMPORARY TABLE ... ENGINE=Memory, the parser calls resolve_engine() which fails because the MEMORY engine isn't loaded during early bootstrap. This sets error 1286 (ER_UNKNOWN_STORAGE_ENGINE) in the THD diagnostics area. The error is never cleared.

In check_table_funs, for partitioned tables with function-based expressions (e.g., PARTITION BY RANGE (month(col))), the code calls fix_partition_func which calls part_val_int. In MySQL 8.4, part_val_int checks current_thd->is_error() unconditionally after val_int(). It sees the stale error 1286 from the stored procedure check and returns failure, even though the partition expression evaluated correctly.

In MySQL 8.0, part_val_int only checked is_error() inside the null_value branch, so stale THD errors did not affect partition expression evaluation.

The behavior change in part_val_int (sql/sql_partition.cc):

8.0: https://github.com/mysql/mysql-server/blob/mysql-8.0.40/sql/sql_partition.cc
  *result = item_expr->val_int();
  if (item_expr->null_value) {
    if (current_thd->is_error()) return true;
    *result = LLONG_MIN;
  }
  return false;

8.4:  https://github.com/mysql/mysql-server/blob/mysql-8.4.0/sql/sql_partition.cc
  *result = item_expr->val_int();
  if (current_thd->is_error()) return true;  // unconditional
  if (item_expr->null_value) {
    *result = LLONG_MIN;
  }
  return false;

The error is not logged to the error log. The only visible symptom is:
  [MY-013135] Incorrect information in file: './db/table.frm'
  [MY-014078] Can not open table; functions in constraints, partitions, or virtual columns may have failed.
  [MY-010020] Data Dictionary initialization failed.

The .frm reference is misleading as there are no .frm files on MySQL 8.0 instances.

Confirmed via GDB: calling thd->clear_error() before fix_partition_func runs allows the upgrade to complete successfully.

Related: Bug #118347

How to repeat:
1. Install MySQL 8.0.40 and initialize a data directory.

2. Connect and create the following:

CREATE DATABASE test_repro;
USE test_repro;

DELIMITER //
CREATE PROCEDURE cleanup_proc()
BEGIN
  CREATE TEMPORARY TABLE IF NOT EXISTS temp_ids (
    id BIGINT PRIMARY KEY
  ) ENGINE=Memory;
  DROP TEMPORARY TABLE IF EXISTS temp_ids;
END //
DELIMITER ;

CREATE TABLE test_partition (
  id BIGINT NOT NULL AUTO_INCREMENT,
  dt DATETIME NOT NULL,
  PRIMARY KEY (id, dt)
) PARTITION BY RANGE (month(dt)) (
  PARTITION p01 VALUES LESS THAN (2),
  PARTITION p02 VALUES LESS THAN (3),
  PARTITION p03 VALUES LESS THAN (4),
  PARTITION p04 VALUES LESS THAN (13)
);

3. Stop the 8.0.40 server.

4. Start the 8.4.7 binary against the same data directory.

5. The upgrade fails with:

2026-04-22T19:16:50.383880Z 1 [ERROR] [MY-013135] [Server] Incorrect information in file: './test_repro/test_partition.frm'
2026-04-22T19:16:50.383906Z 1 [Warning] [MY-014078] [Server] Can not open table `test_repro`.`test_partition`; functions in constraints, partitions, or virtual columns may have failed.
2026-04-22T19:16:50.383919Z 1 [Note] [MY-014079] [Server] TABLE `test_repro`.`test_partition` = { PARTITION = { expr: "month(`dt`)"; };};
2026-04-22T19:16:50.386026Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.

6. Drop the stored procedure and retry. The upgrade succeeds.

7. Create a fresh 8.0.40 instance with only the partition table (no stored procedure). Upgrade to 8.4.7. The upgrade succeeds.

Suggested fix:
Either:

1. Clear the THD error state in do_server_upgrade_checks between the check_routines and check_table_funs phases (sql/dd/impl/upgrade/server.cc).

2. Clear the THD error state in check_table_funs before processing each table (sql/dd/impl/upgrade/server.cc, before the open_table call).

3. Revert part_val_int to only check is_error() inside the null_value branch, matching the 8.0 behavior (sql/sql_partition.cc).
[23 Apr 6:32] Praveenkumar Hulakund
Thank you for reporting this issue. We will take a look at it.