Skip to content

Commit 7060360

Browse files
Dyre TjeldvollDyre Tjeldvoll
Dyre Tjeldvoll
authored and
Dyre Tjeldvoll
committed
Bug#30943642: ERROR 1846 (0A000) AT LINE 1: ALGORITHM=INPLACE IS NOT SUPPORTED. REASON: CANNO
Problem: ALTER on a table with a SET column which had a display width > 255 would not be done INPLACE, even if otherwise possible. Solution: Fix incorrect inplace check for SETs (display width is irrelevant for SETS (and enums) since this does not affect the amount storage needed. Change-Id: Ide8743047de62f87ed5e2cf268f447d4c93d6470
1 parent bfbe8d2 commit 7060360

File tree

5 files changed

+123
-18
lines changed

5 files changed

+123
-18
lines changed

mysql-test/r/alter_table.result

+34
Original file line numberDiff line numberDiff line change
@@ -4425,3 +4425,37 @@ CREATE TABLE t1 (b INT);
44254425
# The below ALTER TABLE causes assertion failure without the fix.
44264426
ALTER TABLE t1 ADD gcol INT AS (b + 1) VIRTUAL FIRST, ADD COLUMN a INT;
44274427
DROP TABLE t1;
4428+
#
4429+
# Bug#30943642 ERROR 1846 (0A000) AT LINE 1: ALGORITHM=INPLACE IS NOT
4430+
# SUPPORTED. REASON: CANNO
4431+
#
4432+
CREATE TABLE t1 (c1
4433+
SET('1234567890123456789a','1234567890123456789b','12345678901234567890c'));
4434+
ALTER TABLE t1 ADD c2 INT NULL AFTER c1, ALGORITHM=INPLACE;
4435+
DROP TABLE t1;
4436+
CREATE TABLE t1 (c1
4437+
SET('1234567890123456789a','1234567890123456789b','12345678901234567890cd')
4438+
DEFAULT NULL);
4439+
# Verify that it is possible to add column to table with set column
4440+
# having display width in bytes >= 256
4441+
ALTER TABLE t1 ADD c2 INT NULL AFTER c1, ALGORITHM=INPLACE;
4442+
DROP TABLE t1;
4443+
# Enums are not affected, because in order for display width in bytes
4444+
# to exceed 255 we need an invidual enum value with this this size,
4445+
# and this is not permitted.
4446+
CREATE TABLE t1 (c1 ENUM ('000', '001',
4447+
'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'));
4448+
ERROR HY000: Too long enumeration/set value for column c1.
4449+
CREATE TABLE t1 (c1 SET ('00', '01', '02', '03', '04', '05', '06'));
4450+
# Verify that a SET change which requires more space still cannot be
4451+
# done inplace
4452+
ALTER TABLE t1 MODIFY COLUMN c1 SET ('00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15'), ALGORITHM=INPLACE;
4453+
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
4454+
DROP TABLE t1;
4455+
CREATE TABLE t1 (c1 ENUM ('000', '001', '002', '003'));
4456+
# Verify that an ENUM change which requires more space still cannot be
4457+
# done inplace
4458+
ALTER TABLE t1 MODIFY COLUMN c1 ENUM (
4459+
'000', '001', '002', '003', '004', '005', '006', '007', '008', '009', '010', '011', '012', '013', '014', '015', '016', '017', '018', '019', '020', '021', '022', '023', '024', '025', '026', '027', '028', '029', '030', '031', '032', '033', '034', '035', '036', '037', '038', '039', '040', '041', '042', '043', '044', '045', '046', '047', '048', '049', '050', '051', '052', '053', '054', '055', '056', '057', '058', '059', '060', '061', '062', '063', '064', '065', '066', '067', '068', '069', '070', '071', '072', '073', '074', '075', '076', '077', '078', '079', '080', '081', '082', '083', '084', '085', '086', '087', '088', '089', '090', '091', '092', '093', '094', '095', '096', '097', '098', '099', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', '217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', '237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256'), ALGORITHM=INPLACE;
4460+
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
4461+
DROP TABLE t1;

mysql-test/t/alter_table.test

+44
Original file line numberDiff line numberDiff line change
@@ -3546,3 +3546,47 @@ CREATE TABLE t1 (b INT);
35463546
ALTER TABLE t1 ADD gcol INT AS (b + 1) VIRTUAL FIRST, ADD COLUMN a INT;
35473547
DROP TABLE t1;
35483548

3549+
3550+
--echo #
3551+
--echo # Bug#30943642 ERROR 1846 (0A000) AT LINE 1: ALGORITHM=INPLACE IS NOT
3552+
--echo # SUPPORTED. REASON: CANNO
3553+
--echo #
3554+
3555+
CREATE TABLE t1 (c1
3556+
SET('1234567890123456789a','1234567890123456789b','12345678901234567890c'));
3557+
ALTER TABLE t1 ADD c2 INT NULL AFTER c1, ALGORITHM=INPLACE;
3558+
DROP TABLE t1;
3559+
3560+
CREATE TABLE t1 (c1
3561+
SET('1234567890123456789a','1234567890123456789b','12345678901234567890cd')
3562+
DEFAULT NULL);
3563+
3564+
--echo # Verify that it is possible to add column to table with set column
3565+
--echo # having display width in bytes >= 256
3566+
ALTER TABLE t1 ADD c2 INT NULL AFTER c1, ALGORITHM=INPLACE;
3567+
DROP TABLE t1;
3568+
3569+
--echo # Enums are not affected, because in order for display width in bytes
3570+
--echo # to exceed 255 we need an invidual enum value with this this size,
3571+
--echo # and this is not permitted.
3572+
--error ER_TOO_LONG_SET_ENUM_VALUE
3573+
CREATE TABLE t1 (c1 ENUM ('000', '001',
3574+
'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'));
3575+
3576+
CREATE TABLE t1 (c1 SET ('00', '01', '02', '03', '04', '05', '06'));
3577+
3578+
--echo # Verify that a SET change which requires more space still cannot be
3579+
--echo # done inplace
3580+
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
3581+
ALTER TABLE t1 MODIFY COLUMN c1 SET ('00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15'), ALGORITHM=INPLACE;
3582+
DROP TABLE t1;
3583+
3584+
CREATE TABLE t1 (c1 ENUM ('000', '001', '002', '003'));
3585+
3586+
--echo # Verify that an ENUM change which requires more space still cannot be
3587+
--echo # done inplace
3588+
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
3589+
ALTER TABLE t1 MODIFY COLUMN c1 ENUM (
3590+
'000', '001', '002', '003', '004', '005', '006', '007', '008', '009', '010', '011', '012', '013', '014', '015', '016', '017', '018', '019', '020', '021', '022', '023', '024', '025', '026', '027', '028', '029', '030', '031', '032', '033', '034', '035', '036', '037', '038', '039', '040', '041', '042', '043', '044', '045', '046', '047', '048', '049', '050', '051', '052', '053', '054', '055', '056', '057', '058', '059', '060', '061', '062', '063', '064', '065', '066', '067', '068', '069', '070', '071', '072', '073', '074', '075', '076', '077', '078', '079', '080', '081', '082', '083', '084', '085', '086', '087', '088', '089', '090', '091', '092', '093', '094', '095', '096', '097', '098', '099', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '210', '211', '212', '213', '214', '215', '216', '217', '218', '219', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '230', '231', '232', '233', '234', '235', '236', '237', '238', '239', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '250', '251', '252', '253', '254', '255', '256'), ALGORITHM=INPLACE;
3591+
DROP TABLE t1;
3592+

sql/field.cc

+40-17
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ namespace {
132132
condition, false otherwise.
133133
*/
134134
bool sql_type_prevents_inplace(const Field &from, const Create_field &to) {
135+
DBUG_TRACE;
135136
return to.sql_type != from.real_type();
136137
}
137138

@@ -147,19 +148,35 @@ bool sql_type_prevents_inplace(const Field &from, const Create_field &to) {
147148
condition, false otherwise.
148149
*/
149150
bool length_prevents_inplace(const Field &from, const Create_field &to) {
150-
DBUG_PRINT("inplace", ("stmt: %s", current_thd->query().str));
151-
152-
DBUG_PRINT("inplace", ("from: field_length:%u, pack_length():%u, "
153-
"row_pack_length():%u, max_display_length():%u",
154-
from.field_length, from.pack_length(),
155-
from.row_pack_length(), from.max_display_length()));
156-
157-
DBUG_PRINT("inplace", ("to: length:%zu, pack_length:%zu",
158-
to.max_display_width_in_bytes(), to.pack_length()));
151+
DBUG_TRACE;
152+
DBUG_PRINT(
153+
"inplace",
154+
("from:%p, to.field:%p, to.field->row_pack_length():%u, "
155+
"to.max_display_width_in_bytes():%zu",
156+
&from, to.field, to.field ? to.field->row_pack_length() : (uint)-1,
157+
to.max_display_width_in_bytes()));
158+
159+
if (to.pack_length() < from.pack_length()) {
160+
DBUG_PRINT(
161+
"inplace",
162+
("decreasing pack_length from %u to %zu, -> true for '%s'",
163+
from.pack_length(), to.pack_length(), current_thd->query().str));
164+
return true;
165+
}
159166

160-
return (
161-
to.pack_length() < from.pack_length() ||
162-
(to.max_display_width_in_bytes() >= 256 && from.row_pack_length() < 256));
167+
if (to.max_display_width_in_bytes() >= 256 && from.row_pack_length() < 256) {
168+
DBUG_PRINT("inplace",
169+
("row_pack_length increases past the 256 threshold, from %u to "
170+
"%zu, -> true for '%s'",
171+
from.row_pack_length(), to.max_display_width_in_bytes(),
172+
current_thd->query().str));
173+
DBUG_PRINT("inplace",
174+
("from:%p, to.field:%p, to.field->row_pack_length():%u", &from,
175+
to.field, to.field ? to.field->row_pack_length() : (uint)-1));
176+
return true;
177+
}
178+
DBUG_PRINT("inplace", ("-> false"));
179+
return false;
163180
}
164181

165182
/**
@@ -188,6 +205,8 @@ bool length_prevents_inplace(const Field &from, const Create_field &to) {
188205
condition, false otherwise.
189206
*/
190207
bool charset_prevents_inplace(const Field_str &from, const Create_field &to) {
208+
DBUG_TRACE;
209+
191210
if (my_charset_same(to.charset, from.charset()) ||
192211
my_charset_same(to.charset, &my_charset_bin)) {
193212
return false;
@@ -208,6 +227,7 @@ bool charset_prevents_inplace(const Field_str &from, const Create_field &to) {
208227
condition, false otherwise.
209228
*/
210229
bool change_prevents_inplace(const Field_str &from, const Create_field &to) {
230+
DBUG_TRACE;
211231
return sql_type_prevents_inplace(from, to) ||
212232
length_prevents_inplace(from, to) ||
213233
charset_prevents_inplace(from, to);
@@ -6051,6 +6071,8 @@ bool Field::gcol_expr_is_equal(const Create_field *field) const {
60516071
}
60526072

60536073
uint Field_str::is_equal(const Create_field *new_field) const {
6074+
DBUG_TRACE;
6075+
60546076
if (change_prevents_inplace(*this, *new_field)) {
60556077
return IS_EQUAL_NO;
60566078
}
@@ -6745,6 +6767,7 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table,
67456767
}
67466768

67476769
uint Field_varstring::is_equal(const Create_field *new_field) const {
6770+
DBUG_TRACE;
67486771
if (change_prevents_inplace(*this, *new_field)) {
67496772
return IS_EQUAL_NO;
67506773
}
@@ -7281,6 +7304,8 @@ uint Field_blob::max_packed_col_length() const {
72817304
}
72827305

72837306
uint Field_blob::is_equal(const Create_field *new_field) const {
7307+
DBUG_TRACE;
7308+
72847309
// Can't use change_prevents_inplace() here as it uses
72857310
// sql_type_prevents_inplace() which checks real_type(), and
72867311
// Field_blob::real_type() does NOT return the actual blob type as
@@ -8299,17 +8324,15 @@ bool Field_enum::eq_def(const Field *field) const {
82998324
*/
83008325

83018326
uint Field_enum::is_equal(const Create_field *new_field) const {
8327+
DBUG_TRACE;
83028328
/*
83038329
The fields are compatible if they have the same flags,
83048330
type, charset and have the same underlying length.
83058331
*/
8306-
if (change_prevents_inplace(*this, *new_field)) {
8307-
DBUG_PRINT("inplace", ("change_prevents_inplace() -> IS_EQUAL_NO"));
8332+
if (sql_type_prevents_inplace(*this, *new_field)) {
8333+
DBUG_PRINT("inplace", ("-> IS_EQUAL_NO"));
83088334
return IS_EQUAL_NO;
83098335
}
8310-
// Assert - either the charset is unchanged or the change is
8311-
// inplace-compatible.
8312-
83138336
TYPELIB *new_typelib = new_field->interval;
83148337

83158338
/*

sql/sql_alter.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ class Alter_info {
326326

327327
/// Set if ANY engine attribute is used (also in CREATE) Note that
328328
/// this is NOT to be set for SECONDARY_ENGINE_ATTRIBUTE as this flag
329-
/// controls if execution schould check if SE supports engine
329+
/// controls if execution should check if SE supports engine
330330
/// attributes.
331331
ANY_ENGINE_ATTRIBUTE = 1ULL << 39
332332
};

sql/sql_table.cc

+4
Original file line numberDiff line numberDiff line change
@@ -11234,6 +11234,8 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table,
1123411234
*/
1123511235
uint old_field_index_without_vgc = 0;
1123611236
for (f_ptr = table->field; (field = *f_ptr); f_ptr++) {
11237+
DBUG_PRINT("inplace", ("Existing field: %s", field->field_name));
11238+
1123711239
/* Clear marker for renamed or dropped field
1123811240
which we are going to set later. */
1123911241
field->clear_flag(FIELD_IS_RENAMED);
@@ -11257,6 +11259,8 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table,
1125711259
*/
1125811260
switch (field->is_equal(new_field)) {
1125911261
case IS_EQUAL_NO:
11262+
DBUG_PRINT("inplace", ("Field %s: IS_EQUAL_NO for '%s'",
11263+
field->field_name, thd->query().str));
1126011264
/* New column type is incompatible with old one. */
1126111265
if (field->is_virtual_gcol())
1126211266
ha_alter_info->handler_flags |=

0 commit comments

Comments
 (0)