Re: [Maria-developers] 6768e3a2830: MDEV-22166 MIGRATE PARTITION: move out partition into a table
Hi, Aleksey! It's great that you made it atomic. Frankly, I didn't think of it, MDEV defines the feature as being exactly equivalent to the 3-command sequence, so non-atomic. But, of course, making it atomic makes perfect sense. See other comments below. On Aug 23, Aleksey Midenkov wrote:
commit 6768e3a2830 Author: Aleksey Midenkov
Date: Thu Jul 29 22:54:12 2021 +0300 diff --git a/sql/lex.h b/sql/lex.h index cbf9d9d51b2..55eefc39a7e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -240,6 +240,7 @@ SYMBOL symbols[] = { { "EXPLAIN", SYM(DESCRIBE)}, { "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)}, + { "EXTRACT", SYM(EXTRACT_SYM)},
So, you did EXTRACT after all, not MIGRATE? ADD/EXTRACT aren't opposites in SQL. It would be rather consistent to have ALTER ... ADD PARTITION (...) FROM table_name and ALTER ... DROP PARTITION ... TO table_name except that DROP...TO looks kind of strange, and ADD...FROM does not convey the meaning that the table disappears. The second issue also applies to IMPORT/EXPORT. Another option, also kind of strange, but also consistent and makes it clear that the table/partition disappears: ALTER ... MOVE TABLE table_name TO PARTITION (...) ALTER ... MOVE PARTITION ... TO TABLE table_name or the same with CHANGE instead of MOVE to reuse an existing keyword. I'm not saying anything of the above is perfect, and better variants are very much welcome. But pretty much anything is better than ADD/EXTRACT.
{ "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, { "FAULTS", SYM(FAULTS_SYM)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index dc2eb4425f0..a41ea7d3e4a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7605,6 +7605,25 @@ alter_commands: if (Lex->stmt_alter_table_exchange_partition($6)) MYSQL_YYABORT; } + | EXTRACT_SYM PARTITION_SYM alt_part_name_item + AS TABLE_SYM table_ident have_partitioning + { + LEX *lex= Lex; + lex->first_select_lex()->db= $6->db; + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) + MYSQL_YYABORT; + if (unlikely(check_table_name($6->table.str,$6->table.length, + FALSE)) || + ($6->db.str && unlikely(check_db_name((LEX_STRING*) &$6->db)))) + my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $6->table.str));
good point, LEX::stmt_alter_table_exchange_partition() doesn't seem to do it
+ lex->name= $6->table; + + lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table(); + if (unlikely(lex->m_sql_cmd == NULL)) + MYSQL_YYABORT; + lex->alter_info.partition_flags|= ALTER_PARTITION_EXTRACT;
why wouldn't you combine the common code from here and EXCHANGE PARTITION? less code duplication and as a bonus EXCHANGE will get proper table/db name checks.
+ } ;
remove_partitioning: diff --git a/sql/sql_alter.h b/sql/sql_alter.h index a0f89c28d2a..6aa65d232ca 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -345,6 +348,8 @@ class Alter_table_ctx /** Indicates that we are altering temporary table */ bool tmp_table;
+ DDL_LOG_STATE *ddl_log_state;
What do you need this for?
+ private: char new_filename[FN_REFLEN + 1]; char new_alias_buff[NAME_LEN + 1]; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 779d125af70..033d77a827d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10016,7 +10146,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, }
// In-place execution of ALTER TABLE for partitioning. - DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, + DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, &alter_ctx, create_info, table_list, &alter_ctx.db, &alter_ctx.table_name));
you no longer need to pass alter_ctx.db and alter_ctx.table_name, if you pass the whole alter_ctx down.
diff --git a/include/my_dbug.h b/include/my_dbug.h index e25bfcf28a7..cf969ce5750 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -104,6 +104,8 @@ extern int (*dbug_sanity)(void); (_db_keyword_(0,(keyword), 0) ? (a1) : (a2)) #define DBUG_EVALUATE_IF(keyword,a1,a2) \ (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) +#define DBUG_TRUE_IF(keyword) DBUG_EVALUATE_IF(keyword, 1, 0) +#define DBUG_FALSE_IF(keyword) DBUG_EVALUATE_IF(keyword, 0, 1)
hmm. DBUG_FALSE_IF is not used anywhere, DBUG_TRUE_IF is used once as if (DBUG_TRUE_IF("error_extract_partition_00") || unlikely(error= file->ha_rename_table(from_name, to_name))) and this is typically written as if (DBUG_EVALUATE_IF("error_extract_partition_00", 1, error= file->ha_rename_table(from_name, to_name))) so I see no need for either DBUG_TRUE_IF or DBUG_FALSE_IF, please, remove both
#define DBUG_PRINT(keyword,arglist) \ do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 85d880cbbb4..4172a61812e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5432,7 +5432,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, } while (++part_count < tab_part_info->num_parts); if (num_parts_found != num_parts_dropped) { - my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "DROP"); + my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), cmd);
Not part of your patch, I know, but the error message here is "Error in list of partitions to %-.64s" shouldn't it say "Partition does not exist" or something?
goto err; } if (table->file->is_fk_defined_on_table_or_index(MAX_KEY)) @@ -7268,6 +7420,48 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, if (alter_partition_lock_handling(lpt)) goto err; } + else if (alter_info->partition_flags & ALTER_PARTITION_EXTRACT) + { + if (mysql_write_frm(lpt, WFRM_WRITE_EXTRACTED) || + write_log_drop_shadow_frm(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_1") || + ERROR_INJECT_ERROR("fail_extract_partition_1") || + mysql_write_frm(lpt, WFRM_WRITE_SHADOW) || + ERROR_INJECT_CRASH("crash_extract_partition_2") || + ERROR_INJECT_ERROR("fail_extract_partition_2") || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || + ERROR_INJECT_CRASH("crash_extract_partition_3") || + ERROR_INJECT_ERROR("fail_extract_partition_3") || + write_log_extract_partition(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_4") || + ERROR_INJECT_ERROR("fail_extract_partition_4") || + alter_close_table(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_5") || + ERROR_INJECT_ERROR("fail_extract_partition_5") || + alter_partition_extract(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_7") || + ERROR_INJECT_ERROR("fail_extract_partition_7") || + (frm_install= TRUE, FALSE) || + mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) || + log_partition_alter_to_ddl_log(lpt) || + (frm_install= FALSE, FALSE) || + ERROR_INJECT_CRASH("crash_extract_partition_8") || + ERROR_INJECT_ERROR("fail_extract_partition_8") || + (ddl_log_complete(lpt->part_info), false) ||
as far as I understand this ^^^ should be done *after* binlogging. I suspect that if you crash here, blnlog won't get this ALTER TABLE.
+ ((!thd->lex->no_write_to_binlog) && + (write_bin_log(thd, FALSE, + thd->query(), thd->query_length()), FALSE)) ||
if you crash here, what will roll forward on recovery and drop the backup? The log is already closed here, isn't it? I don't understand why you need a backup. Why not to install shadow after the binlog was written?
+ mysql_write_frm(lpt, WFRM_DROP_BACKUP) || + ERROR_INJECT_CRASH("crash_extract_partition_9") || + ERROR_INJECT_ERROR("fail_extract_partition_9")) + { + (void) ddl_log_revert(thd, lpt->part_info); + handle_alter_part_error(lpt, true, true, frm_install); + goto err; + } + if (alter_partition_lock_handling(lpt)) + goto err; + } else if ((alter_info->partition_flags & ALTER_PARTITION_ADD) && (part_info->part_type == RANGE_PARTITION || part_info->part_type == LIST_PARTITION)) diff --git a/mysql-test/include/lcase_names.inc b/mysql-test/include/lcase_names.inc new file mode 100644 index 00000000000..e69de29bb2d
better put here some comment, like in other dummy *.inc files see e.g. platform.inc or protocol.inc
diff --git a/mysql-test/suite/atomic/alter_partition,aria.rdiff b/mysql-test/suite/atomic/alter_partition,aria.rdiff new file mode 100644 index 00000000000..20c0510c5ed --- /dev/null +++ b/mysql-test/suite/atomic/alter_partition,aria.rdiff @@ -0,0 +1,219 @@ +--- alter_partition.result ++++ alter_partition,aria.reject +@@ -1,4 +1,4 @@ +-set @@default_storage_engine=MyISAM; ++set @@default_storage_engine=Aria; + # Crash recovery + create or replace procedure prepare_table() + begin +@@ -13,12 +13,12 @@ + end $ + # QUERY: ALTER TABLE t1 EXTRACT PARTITION p1 AS TABLE tp1 + # CRASH POINT: ddl_log_create_before_create_frm +-t1#P#p0.MYD +-t1#P#p0.MYI +-t1#P#p1.MYD
may be better `replace_result MAI MYI MAD MYD` ? if that's the only difference. To avoid big rdiff files.
+-t1#P#p1.MYI +-t1#P#pn.MYD +-t1#P#pn.MYI ++t1#P#p0.MAD ++t1#P#p0.MAI
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi Sergei!
The updated branch is cabd0530 bb-10.7-midenok-MDEV-22166
On Wed, Aug 25, 2021 at 9:33 PM Sergei Golubchik
Hi, Aleksey!
It's great that you made it atomic. Frankly, I didn't think of it, MDEV defines the feature as being exactly equivalent to the 3-command sequence, so non-atomic. But, of course, making it atomic makes perfect sense.
See other comments below.
On Aug 23, Aleksey Midenkov wrote:
commit 6768e3a2830 Author: Aleksey Midenkov
Date: Thu Jul 29 22:54:12 2021 +0300 diff --git a/sql/lex.h b/sql/lex.h index cbf9d9d51b2..55eefc39a7e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -240,6 +240,7 @@ SYMBOL symbols[] = { { "EXPLAIN", SYM(DESCRIBE)}, { "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)}, + { "EXTRACT", SYM(EXTRACT_SYM)},
So, you did EXTRACT after all, not MIGRATE?
I did like the original description said but I agree that this should be changed to something better. Moreover EXTRACT parsing is now incorrect, see git show 3b693cd3d9 mysql-test/main/parser.result
ADD/EXTRACT aren't opposites in SQL.
It would be rather consistent to have
ALTER ... ADD PARTITION (...) FROM table_name
and
ALTER ... DROP PARTITION ... TO table_name
except that DROP...TO looks kind of strange, and ADD...FROM does not convey the meaning that the table disappears.
The second issue also applies to IMPORT/EXPORT.
Another option, also kind of strange, but also consistent and makes it clear that the table/partition disappears:
ALTER ... MOVE TABLE table_name TO PARTITION (...) ALTER ... MOVE PARTITION ... TO TABLE table_name
or the same with CHANGE instead of MOVE to reuse an existing keyword.
There is no MOVE symbol and we should not add a new one because of the same compatibility reason: it will not be possible to create table "move" (as well as to work with existing one I suspect). That's why we found MIGRATE as a good candidate And the reasons to have some special keyword, not just "ADD PARTITION ... FROM ..." are: 1. it is not clear whether the source table stays or not (that was the discussion in MDEV-22165); 2. for keyword like MIGRATE it is clear how it works in both directions and no need to remember or guess the opposite keyword; 3. (and most important) is scalability: we may want to expand the syntax for copying the table instead of moving it so instead of MIGRATE we put COPY and that's it: same formula, clear how it works, easy to interchange between MIGRATE and COPY. I've already thought about MOVE as a better keyword but sadly enough it is not reserved. So how about the proposed syntax with MIGRATE?
I'm not saying anything of the above is perfect, and better variants are very much welcome. But pretty much anything is better than ADD/EXTRACT.
{ "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, { "FAULTS", SYM(FAULTS_SYM)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index dc2eb4425f0..a41ea7d3e4a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7605,6 +7605,25 @@ alter_commands: if (Lex->stmt_alter_table_exchange_partition($6)) MYSQL_YYABORT; } + | EXTRACT_SYM PARTITION_SYM alt_part_name_item + AS TABLE_SYM table_ident have_partitioning + { + LEX *lex= Lex; + lex->first_select_lex()->db= $6->db; + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) + MYSQL_YYABORT; + if (unlikely(check_table_name($6->table.str,$6->table.length, + FALSE)) || + ($6->db.str && unlikely(check_db_name((LEX_STRING*) &$6->db)))) + my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $6->table.str));
good point, LEX::stmt_alter_table_exchange_partition() doesn't seem to do it
+ lex->name= $6->table; + + lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table(); + if (unlikely(lex->m_sql_cmd == NULL)) + MYSQL_YYABORT; + lex->alter_info.partition_flags|= ALTER_PARTITION_EXTRACT;
why wouldn't you combine the common code from here and EXCHANGE PARTITION? less code duplication and as a bonus EXCHANGE will get proper table/db name checks.
Updated.
+ } ;
remove_partitioning: diff --git a/sql/sql_alter.h b/sql/sql_alter.h index a0f89c28d2a..6aa65d232ca 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -345,6 +348,8 @@ class Alter_table_ctx /** Indicates that we are altering temporary table */ bool tmp_table;
+ DDL_LOG_STATE *ddl_log_state;
What do you need this for?
Cleaned up this.
+ private: char new_filename[FN_REFLEN + 1]; char new_alias_buff[NAME_LEN + 1]; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 779d125af70..033d77a827d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10016,7 +10146,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, }
// In-place execution of ALTER TABLE for partitioning. - DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, + DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info, &alter_ctx, create_info, table_list, &alter_ctx.db, &alter_ctx.table_name));
you no longer need to pass alter_ctx.db and alter_ctx.table_name, if you pass the whole alter_ctx down.
Cleaned up this.
diff --git a/include/my_dbug.h b/include/my_dbug.h index e25bfcf28a7..cf969ce5750 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -104,6 +104,8 @@ extern int (*dbug_sanity)(void); (_db_keyword_(0,(keyword), 0) ? (a1) : (a2)) #define DBUG_EVALUATE_IF(keyword,a1,a2) \ (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) +#define DBUG_TRUE_IF(keyword) DBUG_EVALUATE_IF(keyword, 1, 0) +#define DBUG_FALSE_IF(keyword) DBUG_EVALUATE_IF(keyword, 0, 1)
hmm. DBUG_FALSE_IF is not used anywhere, DBUG_TRUE_IF is used once as
(1):
if (DBUG_TRUE_IF("error_extract_partition_00") || unlikely(error= file->ha_rename_table(from_name, to_name)))
and this is typically written as
(2):
if (DBUG_EVALUATE_IF("error_extract_partition_00", 1, error= file->ha_rename_table(from_name, to_name)))
so I see no need for either DBUG_TRUE_IF or DBUG_FALSE_IF, please, remove both
Please, (1) looks much better! Considering that there are no complex expressions for a1 in the code but only 1 or 0, we should use DBUG_TRUE_IF/DBUG_FALSE_IF instead. I can change all entries of DBUG_EVALUATE_IF for that. This is supposed to be an independent refactoring.
#define DBUG_PRINT(keyword,arglist) \ do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 85d880cbbb4..4172a61812e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5432,7 +5432,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, } while (++part_count < tab_part_info->num_parts); if (num_parts_found != num_parts_dropped) { - my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "DROP"); + my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), cmd);
Not part of your patch, I know, but the error message here is
"Error in list of partitions to %-.64s"
shouldn't it say "Partition does not exist" or something?
Why does DROP use such wording then? I don't think here should be different error code, but the code name itself should be something like ER_PARTITION_NOT_EXISTS.
goto err; } if (table->file->is_fk_defined_on_table_or_index(MAX_KEY)) @@ -7268,6 +7420,48 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, if (alter_partition_lock_handling(lpt)) goto err; } + else if (alter_info->partition_flags & ALTER_PARTITION_EXTRACT) + { + if (mysql_write_frm(lpt, WFRM_WRITE_EXTRACTED) || + write_log_drop_shadow_frm(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_1") || + ERROR_INJECT_ERROR("fail_extract_partition_1") || + mysql_write_frm(lpt, WFRM_WRITE_SHADOW) || + ERROR_INJECT_CRASH("crash_extract_partition_2") || + ERROR_INJECT_ERROR("fail_extract_partition_2") || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || + ERROR_INJECT_CRASH("crash_extract_partition_3") || + ERROR_INJECT_ERROR("fail_extract_partition_3") || + write_log_extract_partition(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_4") || + ERROR_INJECT_ERROR("fail_extract_partition_4") || + alter_close_table(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_5") || + ERROR_INJECT_ERROR("fail_extract_partition_5") || + alter_partition_extract(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_7") || + ERROR_INJECT_ERROR("fail_extract_partition_7") || + (frm_install= TRUE, FALSE) || + mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) || + log_partition_alter_to_ddl_log(lpt) || + (frm_install= FALSE, FALSE) || + ERROR_INJECT_CRASH("crash_extract_partition_8") || + ERROR_INJECT_ERROR("fail_extract_partition_8") || + (ddl_log_complete(lpt->part_info), false) ||
as far as I understand this ^^^ should be done *after* binlogging. I suspect that if you crash here, blnlog won't get this ALTER TABLE.
Right, I fixed that by reordering calls and using XID.
+ ((!thd->lex->no_write_to_binlog) && + (write_bin_log(thd, FALSE, + thd->query(), thd->query_length()), FALSE)) ||
if you crash here, what will roll forward on recovery and drop the backup? The log is already closed here, isn't it?
I don't understand why you need a backup. Why not to install shadow after the binlog was written?
If we install shadow after binlog was written and before ddl_log_complete() and it crashes after binlog was written and before ddl_log_complete() the chain will be closed via XID and we are left with (or without) original frm and without installed frm. Let's imagine we do not close chain via XID, then it is replayed back and we are left with master-slave inconsistency. There are more examples of how it can crash and how we can try to recover, but the simplest and most reliable implementation is via WFRM_BACKUP_ORIGINAL. If you want to discuss more, let's do that in chat.
+ mysql_write_frm(lpt, WFRM_DROP_BACKUP) || + ERROR_INJECT_CRASH("crash_extract_partition_9") || + ERROR_INJECT_ERROR("fail_extract_partition_9")) + { + (void) ddl_log_revert(thd, lpt->part_info); + handle_alter_part_error(lpt, true, true, frm_install); + goto err; + } + if (alter_partition_lock_handling(lpt)) + goto err; + } else if ((alter_info->partition_flags & ALTER_PARTITION_ADD) && (part_info->part_type == RANGE_PARTITION || part_info->part_type == LIST_PARTITION)) diff --git a/mysql-test/include/lcase_names.inc b/mysql-test/include/lcase_names.inc new file mode 100644 index 00000000000..e69de29bb2d
better put here some comment, like in other dummy *.inc files see e.g. platform.inc or protocol.inc
Done.
diff --git a/mysql-test/suite/atomic/alter_partition,aria.rdiff b/mysql-test/suite/atomic/alter_partition,aria.rdiff new file mode 100644 index 00000000000..20c0510c5ed --- /dev/null +++ b/mysql-test/suite/atomic/alter_partition,aria.rdiff @@ -0,0 +1,219 @@ +--- alter_partition.result ++++ alter_partition,aria.reject +@@ -1,4 +1,4 @@ +-set @@default_storage_engine=MyISAM; ++set @@default_storage_engine=Aria; + # Crash recovery + create or replace procedure prepare_table() + begin +@@ -13,12 +13,12 @@ + end $ + # QUERY: ALTER TABLE t1 EXTRACT PARTITION p1 AS TABLE tp1 + # CRASH POINT: ddl_log_create_before_create_frm +-t1#P#p0.MYD +-t1#P#p0.MYI +-t1#P#p1.MYD
may be better `replace_result MAI MYI MAD MYD` ? if that's the only difference. To avoid big rdiff files.
Done.
+-t1#P#p1.MYI +-t1#P#pn.MYD +-t1#P#pn.MYI ++t1#P#p0.MAD ++t1#P#p0.MAI
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! Some replies. On Aug 26, Aleksey Midenkov wrote:
diff --git a/sql/lex.h b/sql/lex.h index cbf9d9d51b2..55eefc39a7e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -240,6 +240,7 @@ SYMBOL symbols[] = { { "EXPLAIN", SYM(DESCRIBE)}, { "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)}, + { "EXTRACT", SYM(EXTRACT_SYM)},
So, you did EXTRACT after all, not MIGRATE?
I did like the original description said but I agree that this should be changed to something better. Moreover EXTRACT parsing is now incorrect, see
git show 3b693cd3d9 mysql-test/main/parser.result
Yes, I've noticed, didn't comment because we still discuss the syntax. If we'll decide to use EXTRACT after all, then perhaps it could be made non-reserved.
ADD/EXTRACT aren't opposites in SQL.
It would be rather consistent to have
ALTER ... ADD PARTITION (...) FROM table_name
and
ALTER ... DROP PARTITION ... TO table_name
except that DROP...TO looks kind of strange, and ADD...FROM does not convey the meaning that the table disappears.
The second issue also applies to IMPORT/EXPORT.
Another option, also kind of strange, but also consistent and makes it clear that the table/partition disappears:
ALTER ... MOVE TABLE table_name TO PARTITION (...) ALTER ... MOVE PARTITION ... TO TABLE table_name
or the same with CHANGE instead of MOVE to reuse an existing keyword.
There is no MOVE symbol and we should not add a new one because of the same compatibility reason: it will not be possible to create table "move" (as well as to work with existing one I suspect).
it will be, if MOVE won't be a reserved work. But still, keywords, even non-reserved, make the parser a bit slower. And may be a keyword in that context has to be reserved? So, yes, I totally agree that it's best to avoid adding new keywords to the grammar.
That's why we found MIGRATE as a good candidate And the reasons to have some special keyword, not just "ADD PARTITION ... FROM ..." are:
1. it is not clear whether the source table stays or not (that was the discussion in MDEV-22165); 2. for keyword like MIGRATE it is clear how it works in both directions and no need to remember or guess the opposite keyword; 3. (and most important) is scalability: we may want to expand the syntax for copying the table instead of moving it so instead of MIGRATE we put COPY and that's it: same formula, clear how it works, easy to interchange between MIGRATE and COPY.
I've already thought about MOVE as a better keyword but sadly enough it is not reserved. So how about the proposed syntax with MIGRATE?
MIGRATE is not reserved, by the way, it's a non-reserved keyword. If it's my suggested synax from above, but with MIGRATE, it becomes ALTER TABLE ... MIGRATE TABLE tbl_name TO PARTITION (partition definition) ALTER TABLE ... MIGRATE PARTITION part_name TO TABLE tbl_name so very symmetrical. ALTER TABLE ... ADD PARTITION ... MIGRATE FROM TABLE ... looks kind of backward to me. At least if the reverse is MIGRATE PARTITION TO TABLE. May be MIGRATE PARTITION TO TABLE and MIGRATE PARTITION FROM TABLE ? Instead of MIGRATE TABLE FROM PARTITION.
I'm not saying anything of the above is perfect, and better variants are very much welcome. But pretty much anything is better than ADD/EXTRACT.
{ "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, { "FAULTS", SYM(FAULTS_SYM)}, diff --git a/include/my_dbug.h b/include/my_dbug.h index e25bfcf28a7..cf969ce5750 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -104,6 +104,8 @@ extern int (*dbug_sanity)(void); (_db_keyword_(0,(keyword), 0) ? (a1) : (a2)) #define DBUG_EVALUATE_IF(keyword,a1,a2) \ (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) +#define DBUG_TRUE_IF(keyword) DBUG_EVALUATE_IF(keyword, 1, 0) +#define DBUG_FALSE_IF(keyword) DBUG_EVALUATE_IF(keyword, 0, 1)
hmm. DBUG_FALSE_IF is not used anywhere, DBUG_TRUE_IF is used once as if (DBUG_TRUE_IF("error_extract_partition_00") || unlikely(error= file->ha_rename_table(from_name, to_name)))
and this is typically written as
if (DBUG_EVALUATE_IF("error_extract_partition_00", 1, error= file->ha_rename_table(from_name, to_name)))
so I see no need for either DBUG_TRUE_IF or DBUG_FALSE_IF, please, remove both
Please, (1) looks much better! Considering that there are no complex expressions for a1 in the code but only 1 or 0, we should use DBUG_TRUE_IF/DBUG_FALSE_IF instead. I can change all entries of DBUG_EVALUATE_IF for that. This is supposed to be an independent refactoring.
Okay, indeed, it seems that DBUG_EVALUATE_IF is almost always used with one of the arguments being 0 or 1. If you replace all DBUG_EVALUATE_IF's, let's just remove it completely. Note, that DBUG_TRUE_IF can be defined simply as #define DBUG_TRUE_IF(keyword) _db_keyword_(0, (keyword), 1) so may be you'd like to call id DBUG_KEYWORD_IF or something? Although DBUG_TRUE_IF is shorter :)
#define DBUG_PRINT(keyword,arglist) \ do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 85d880cbbb4..4172a61812e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5432,7 +5432,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, } while (++part_count < tab_part_info->num_parts); if (num_parts_found != num_parts_dropped) { - my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "DROP"); + my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), cmd);
Not part of your patch, I know, but the error message here is
"Error in list of partitions to %-.64s"
shouldn't it say "Partition does not exist" or something?
Why does DROP use such wording then? I don't think here should be different error code, but the code name itself should be something like ER_PARTITION_NOT_EXISTS.
I don't know why. I agree it should be ER_PARTITION_NOT_EXISTS, not a different error code. I meant that perhaps we should fix the error message text?
goto err; } if (table->file->is_fk_defined_on_table_or_index(MAX_KEY)) @@ -7268,6 +7420,48 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, if (alter_partition_lock_handling(lpt)) goto err; } + else if (alter_info->partition_flags & ALTER_PARTITION_EXTRACT) + { + if (mysql_write_frm(lpt, WFRM_WRITE_EXTRACTED) || + write_log_drop_shadow_frm(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_1") || + ERROR_INJECT_ERROR("fail_extract_partition_1") || + mysql_write_frm(lpt, WFRM_WRITE_SHADOW) || + ERROR_INJECT_CRASH("crash_extract_partition_2") || + ERROR_INJECT_ERROR("fail_extract_partition_2") || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || + ERROR_INJECT_CRASH("crash_extract_partition_3") || + ERROR_INJECT_ERROR("fail_extract_partition_3") || + write_log_extract_partition(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_4") || + ERROR_INJECT_ERROR("fail_extract_partition_4") || + alter_close_table(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_5") || + ERROR_INJECT_ERROR("fail_extract_partition_5") || + alter_partition_extract(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_7") || + ERROR_INJECT_ERROR("fail_extract_partition_7") || + (frm_install= TRUE, FALSE) || + mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) || + log_partition_alter_to_ddl_log(lpt) || + (frm_install= FALSE, FALSE) || + ERROR_INJECT_CRASH("crash_extract_partition_8") || + ERROR_INJECT_ERROR("fail_extract_partition_8") || + (ddl_log_complete(lpt->part_info), false) || + ((!thd->lex->no_write_to_binlog) && + (write_bin_log(thd, FALSE, + thd->query(), thd->query_length()), FALSE)) ||
if you crash here, what will roll forward on recovery and drop the backup? The log is already closed here, isn't it?
I don't understand why you need a backup. Why not to install shadow after the binlog was written?
If we install shadow after binlog was written and before ddl_log_complete() and it crashes after binlog was written and before ddl_log_complete() the chain will be closed via XID and we are left with (or without) original frm and without installed frm. Let's imagine we do not close chain via XID, then it is replayed back and we are left with master-slave inconsistency. There are more examples of how it can crash and how we can try to recover, but the simplest and most reliable implementation is via WFRM_BACKUP_ORIGINAL. If you want to discuss more, let's do that in chat.
ok. let me check the new patch first, may be it'll answer my questions.
+ mysql_write_frm(lpt, WFRM_DROP_BACKUP) || + ERROR_INJECT_CRASH("crash_extract_partition_9") || + ERROR_INJECT_ERROR("fail_extract_partition_9")) + { + (void) ddl_log_revert(thd, lpt->part_info); + handle_alter_part_error(lpt, true, true, frm_install); + goto err; + } + if (alter_partition_lock_handling(lpt)) + goto err; + }
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi Sergei!
Updated bb-10.7-midenok-MDEV-22166 is d4668e7254c6
On Thu, Aug 26, 2021 at 9:58 PM Sergei Golubchik
Hi, Aleksey!
Some replies.
On Aug 26, Aleksey Midenkov wrote:
diff --git a/sql/lex.h b/sql/lex.h index cbf9d9d51b2..55eefc39a7e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -240,6 +240,7 @@ SYMBOL symbols[] = { { "EXPLAIN", SYM(DESCRIBE)}, { "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)}, + { "EXTRACT", SYM(EXTRACT_SYM)},
So, you did EXTRACT after all, not MIGRATE?
I did like the original description said but I agree that this should be changed to something better. Moreover EXTRACT parsing is now incorrect, see
git show 3b693cd3d9 mysql-test/main/parser.result
Yes, I've noticed, didn't comment because we still discuss the syntax. If we'll decide to use EXTRACT after all, then perhaps it could be made non-reserved.
ADD/EXTRACT aren't opposites in SQL.
It would be rather consistent to have
ALTER ... ADD PARTITION (...) FROM table_name
and
ALTER ... DROP PARTITION ... TO table_name
except that DROP...TO looks kind of strange, and ADD...FROM does not convey the meaning that the table disappears.
The second issue also applies to IMPORT/EXPORT.
Another option, also kind of strange, but also consistent and makes it clear that the table/partition disappears:
ALTER ... MOVE TABLE table_name TO PARTITION (...) ALTER ... MOVE PARTITION ... TO TABLE table_name
or the same with CHANGE instead of MOVE to reuse an existing keyword.
There is no MOVE symbol and we should not add a new one because of the same compatibility reason: it will not be possible to create table "move" (as well as to work with existing one I suspect).
it will be, if MOVE won't be a reserved work. But still, keywords, even non-reserved, make the parser a bit slower. And may be a keyword in that context has to be reserved?
So, yes, I totally agree that it's best to avoid adding new keywords to the grammar.
That's why we found MIGRATE as a good candidate And the reasons to have some special keyword, not just "ADD PARTITION ... FROM ..." are:
1. it is not clear whether the source table stays or not (that was the discussion in MDEV-22165); 2. for keyword like MIGRATE it is clear how it works in both directions and no need to remember or guess the opposite keyword; 3. (and most important) is scalability: we may want to expand the syntax for copying the table instead of moving it so instead of MIGRATE we put COPY and that's it: same formula, clear how it works, easy to interchange between MIGRATE and COPY.
I've already thought about MOVE as a better keyword but sadly enough it is not reserved. So how about the proposed syntax with MIGRATE?
MIGRATE is not reserved, by the way, it's a non-reserved keyword.
If it's my suggested synax from above, but with MIGRATE, it becomes
ALTER TABLE ... MIGRATE TABLE tbl_name TO PARTITION (partition definition) ALTER TABLE ... MIGRATE PARTITION part_name TO TABLE tbl_name
so very symmetrical.
ALTER TABLE ... ADD PARTITION ... MIGRATE FROM TABLE ...
looks kind of backward to me. At least if the reverse is MIGRATE PARTITION TO TABLE.
May be MIGRATE PARTITION TO TABLE and MIGRATE PARTITION FROM TABLE ? Instead of MIGRATE TABLE FROM PARTITION.
Looks nice. Made this kind of syntax.
I'm not saying anything of the above is perfect, and better variants are very much welcome. But pretty much anything is better than ADD/EXTRACT.
{ "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, { "FAULTS", SYM(FAULTS_SYM)}, diff --git a/include/my_dbug.h b/include/my_dbug.h index e25bfcf28a7..cf969ce5750 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -104,6 +104,8 @@ extern int (*dbug_sanity)(void); (_db_keyword_(0,(keyword), 0) ? (a1) : (a2)) #define DBUG_EVALUATE_IF(keyword,a1,a2) \ (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) +#define DBUG_TRUE_IF(keyword) DBUG_EVALUATE_IF(keyword, 1, 0) +#define DBUG_FALSE_IF(keyword) DBUG_EVALUATE_IF(keyword, 0, 1)
hmm. DBUG_FALSE_IF is not used anywhere, DBUG_TRUE_IF is used once as if (DBUG_TRUE_IF("error_extract_partition_00") || unlikely(error= file->ha_rename_table(from_name, to_name)))
and this is typically written as
if (DBUG_EVALUATE_IF("error_extract_partition_00", 1, error= file->ha_rename_table(from_name, to_name)))
so I see no need for either DBUG_TRUE_IF or DBUG_FALSE_IF, please, remove both
Please, (1) looks much better! Considering that there are no complex expressions for a1 in the code but only 1 or 0, we should use DBUG_TRUE_IF/DBUG_FALSE_IF instead. I can change all entries of DBUG_EVALUATE_IF for that. This is supposed to be an independent refactoring.
Okay, indeed, it seems that DBUG_EVALUATE_IF is almost always used with one of the arguments being 0 or 1. If you replace all DBUG_EVALUATE_IF's, let's just remove it completely. Note, that DBUG_TRUE_IF can be defined simply as
#define DBUG_TRUE_IF(keyword) _db_keyword_(0, (keyword), 1)
so may be you'd like to call id DBUG_KEYWORD_IF or something? Although DBUG_TRUE_IF is shorter :)
It turned out DBUG_IF() is even more short! ;)
#define DBUG_PRINT(keyword,arglist) \ do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 85d880cbbb4..4172a61812e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5432,7 +5432,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, } while (++part_count < tab_part_info->num_parts); if (num_parts_found != num_parts_dropped) { - my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "DROP"); + my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), cmd);
Not part of your patch, I know, but the error message here is
"Error in list of partitions to %-.64s"
shouldn't it say "Partition does not exist" or something?
Why does DROP use such wording then? I don't think here should be different error code, but the code name itself should be something like ER_PARTITION_NOT_EXISTS.
I don't know why. I agree it should be ER_PARTITION_NOT_EXISTS, not a different error code. I meant that perhaps we should fix the error message text?
Renamed this error code and ugly ER_KEY_COLUMN_DOES_NOT_EXITS Changed the message.
goto err; } if (table->file->is_fk_defined_on_table_or_index(MAX_KEY)) @@ -7268,6 +7420,48 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, if (alter_partition_lock_handling(lpt)) goto err; } + else if (alter_info->partition_flags & ALTER_PARTITION_EXTRACT) + { + if (mysql_write_frm(lpt, WFRM_WRITE_EXTRACTED) || + write_log_drop_shadow_frm(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_1") || + ERROR_INJECT_ERROR("fail_extract_partition_1") || + mysql_write_frm(lpt, WFRM_WRITE_SHADOW) || + ERROR_INJECT_CRASH("crash_extract_partition_2") || + ERROR_INJECT_ERROR("fail_extract_partition_2") || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || + ERROR_INJECT_CRASH("crash_extract_partition_3") || + ERROR_INJECT_ERROR("fail_extract_partition_3") || + write_log_extract_partition(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_4") || + ERROR_INJECT_ERROR("fail_extract_partition_4") || + alter_close_table(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_5") || + ERROR_INJECT_ERROR("fail_extract_partition_5") || + alter_partition_extract(lpt) || + ERROR_INJECT_CRASH("crash_extract_partition_7") || + ERROR_INJECT_ERROR("fail_extract_partition_7") || + (frm_install= TRUE, FALSE) || + mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) || + log_partition_alter_to_ddl_log(lpt) || + (frm_install= FALSE, FALSE) || + ERROR_INJECT_CRASH("crash_extract_partition_8") || + ERROR_INJECT_ERROR("fail_extract_partition_8") || + (ddl_log_complete(lpt->part_info), false) || + ((!thd->lex->no_write_to_binlog) && + (write_bin_log(thd, FALSE, + thd->query(), thd->query_length()), FALSE)) ||
if you crash here, what will roll forward on recovery and drop the backup? The log is already closed here, isn't it?
I don't understand why you need a backup. Why not to install shadow after the binlog was written?
If we install shadow after binlog was written and before ddl_log_complete() and it crashes after binlog was written and before ddl_log_complete() the chain will be closed via XID and we are left with (or without) original frm and without installed frm. Let's imagine we do not close chain via XID, then it is replayed back and we are left with master-slave inconsistency. There are more examples of how it can crash and how we can try to recover, but the simplest and most reliable implementation is via WFRM_BACKUP_ORIGINAL. If you want to discuss more, let's do that in chat.
ok. let me check the new patch first, may be it'll answer my questions.
+ mysql_write_frm(lpt, WFRM_DROP_BACKUP) || + ERROR_INJECT_CRASH("crash_extract_partition_9") || + ERROR_INJECT_ERROR("fail_extract_partition_9")) + { + (void) ddl_log_revert(thd, lpt->part_info); + handle_alter_part_error(lpt, true, true, frm_install); + goto err; + } + if (alter_partition_lock_handling(lpt)) + goto err; + }
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Aug 30, Aleksey Midenkov wrote:
Hi Sergei!
Updated bb-10.7-midenok-MDEV-22166 is d4668e7254c6
I'll look right after replying to this email.
Okay, indeed, it seems that DBUG_EVALUATE_IF is almost always used with one of the arguments being 0 or 1. If you replace all DBUG_EVALUATE_IF's, let's just remove it completely. Note, that DBUG_TRUE_IF can be defined simply as
#define DBUG_TRUE_IF(keyword) _db_keyword_(0, (keyword), 1)
so may be you'd like to call id DBUG_KEYWORD_IF or something? Although DBUG_TRUE_IF is shorter :)
It turned out DBUG_IF() is even more short! ;)
We have a series of IF_xxx(A,B) macros, IF_PARTITIONING, IF_WIN, etc. IF_DBUG(A,B) expands to A if dbug is compiled in, otherwise into B. having IF_DBUG(A,B) and DBUG_IF(keyword) might be confusing.
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 85d880cbbb4..4172a61812e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc
Renamed this error code and ugly ER_KEY_COLUMN_DOES_NOT_EXITS Changed the message.
Unfortunatey ER_xxx constants are generally part of the API, client applications do if (mysql_errno() == ER_KEY_COLUMN_DOES_NOT_EXITS) ... so renaming cannot be done lightly. Only if really unavoidable and then with a compatibility fallback, like we have now in mysql.h: #define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED #define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN #define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME ...
goto err; }
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi, Sergei!
On Wed, Sep 1, 2021 at 2:58 PM Sergei Golubchik
Hi, Aleksey!
On Aug 30, Aleksey Midenkov wrote:
Hi Sergei!
Updated bb-10.7-midenok-MDEV-22166 is d4668e7254c6
I'll look right after replying to this email.
Okay, indeed, it seems that DBUG_EVALUATE_IF is almost always used with one of the arguments being 0 or 1. If you replace all DBUG_EVALUATE_IF's, let's just remove it completely. Note, that DBUG_TRUE_IF can be defined simply as
#define DBUG_TRUE_IF(keyword) _db_keyword_(0, (keyword), 1)
so may be you'd like to call id DBUG_KEYWORD_IF or something? Although DBUG_TRUE_IF is shorter :)
It turned out DBUG_IF() is even more short! ;)
We have a series of IF_xxx(A,B) macros, IF_PARTITIONING, IF_WIN, etc. IF_DBUG(A,B) expands to A if dbug is compiled in, otherwise into B.
having IF_DBUG(A,B) and DBUG_IF(keyword) might be confusing.
Looks like IF_DBUG is superfluous macro and should be replaced by #ifndef DBUG_OFF #endif But for some code like here IF_DBUG(uchar const *const old_pack_ptr= pack_ptr;,) I'd make DBUG(uchar const *const old_pack_ptr= pack_ptr); So DBUG(A) macro would be a one-liner for #ifndef DBUG_OFF.
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 85d880cbbb4..4172a61812e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc
Renamed this error code and ugly ER_KEY_COLUMN_DOES_NOT_EXITS Changed the message.
Unfortunatey ER_xxx constants are generally part of the API, client applications do
if (mysql_errno() == ER_KEY_COLUMN_DOES_NOT_EXITS) ...
so renaming cannot be done lightly. Only if really unavoidable and then with a compatibility fallback, like we have now in mysql.h:
#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED #define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN #define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME ...
I'd make that anyway with that proxy stuff in mysql.h. C++14 can mark variables deprecated. That can help throw away deprecated constants after some period of time.
goto err; }
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Sep 01, Aleksey Midenkov wrote:
We have a series of IF_xxx(A,B) macros, IF_PARTITIONING, IF_WIN, etc. IF_DBUG(A,B) expands to A if dbug is compiled in, otherwise into B.
having IF_DBUG(A,B) and DBUG_IF(keyword) might be confusing.
Looks like IF_DBUG is superfluous macro and should be replaced by
#ifndef DBUG_OFF #endif
No, it's used in expression. Precisely, to avoid ifdefs.
> diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc > index 85d880cbbb4..4172a61812e 100644 > --- a/sql/sql_partition.cc > +++ b/sql/sql_partition.cc
Renamed this error code and ugly ER_KEY_COLUMN_DOES_NOT_EXITS Changed the message.
Unfortunatey ER_xxx constants are generally part of the API, client applications do
if (mysql_errno() == ER_KEY_COLUMN_DOES_NOT_EXITS) ...
so renaming cannot be done lightly. Only if really unavoidable and then with a compatibility fallback, like we have now in mysql.h:
#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED #define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN #define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME ...
I'd make that anyway with that proxy stuff in mysql.h. C++14 can mark variables deprecated. That can help throw away deprecated constants after some period of time.
Those are defines, I don't know if you can mark them deprecated. About your ER_KEY_COLUMN_DOES_NOT_EXITS replacement: $ grep -c DOES_NOT_EXIST sql/share/errmsg-utf8.txt 6 $ grep -c NOT_EXIST sql/share/errmsg-utf8.txt 7 So only one existing error message uses NOT_EXIST without DOES. Let's keep the conventional naming. So, it should be ER_KEY_DOES_NOT_EXIST ER_KEY_COLUMN_DOES_NOT_EXIST ER_PARTITION_DOES_NOT_EXIST ER_REORG_PARTITION_DOES_NOT_EXIST Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Sergei,
On Wed, Sep 1, 2021 at 9:07 PM Sergei Golubchik
Hi, Aleksey!
On Sep 01, Aleksey Midenkov wrote:
We have a series of IF_xxx(A,B) macros, IF_PARTITIONING, IF_WIN, etc. IF_DBUG(A,B) expands to A if dbug is compiled in, otherwise into B.
having IF_DBUG(A,B) and DBUG_IF(keyword) might be confusing.
Looks like IF_DBUG is superfluous macro and should be replaced by
#ifndef DBUG_OFF #endif
No, it's used in expression. Precisely, to avoid ifdefs.
So, what about DBUG(A) variant?
> > diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc > > index 85d880cbbb4..4172a61812e 100644 > > --- a/sql/sql_partition.cc > > +++ b/sql/sql_partition.cc
Renamed this error code and ugly ER_KEY_COLUMN_DOES_NOT_EXITS Changed the message.
Unfortunatey ER_xxx constants are generally part of the API, client applications do
if (mysql_errno() == ER_KEY_COLUMN_DOES_NOT_EXITS) ...
so renaming cannot be done lightly. Only if really unavoidable and then with a compatibility fallback, like we have now in mysql.h:
#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED #define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN #define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME ...
I'd make that anyway with that proxy stuff in mysql.h. C++14 can mark variables deprecated. That can help throw away deprecated constants after some period of time.
Those are defines, I don't know if you can mark them deprecated.
About your ER_KEY_COLUMN_DOES_NOT_EXITS replacement:
$ grep -c DOES_NOT_EXIST sql/share/errmsg-utf8.txt 6 $ grep -c NOT_EXIST sql/share/errmsg-utf8.txt 7
So only one existing error message uses NOT_EXIST without DOES. Let's keep the conventional naming. So, it should be
ER_KEY_DOES_NOT_EXIST ER_KEY_COLUMN_DOES_NOT_EXIST ER_PARTITION_DOES_NOT_EXIST ER_REORG_PARTITION_DOES_NOT_EXIST
That is longer by the whole useless word...
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Sep 01, Aleksey Midenkov wrote:
Looks like IF_DBUG is superfluous macro and should be replaced by
#ifndef DBUG_OFF #endif
No, it's used in expression. Precisely, to avoid ifdefs.
So, what about DBUG(A) variant?
We have IF_XXX for many different XXX. IF_DBUG was created to follow this convention. Anytime you see a macro IF_XXX you know what it does. Let's keep it that way.
About your ER_KEY_COLUMN_DOES_NOT_EXITS replacement:
$ grep -c DOES_NOT_EXIST sql/share/errmsg-utf8.txt 6 $ grep -c NOT_EXIST sql/share/errmsg-utf8.txt 7
So only one existing error message uses NOT_EXIST without DOES. Let's keep the conventional naming. So, it should be
ER_KEY_DOES_NOT_EXIST ER_KEY_COLUMN_DOES_NOT_EXIST ER_PARTITION_DOES_NOT_EXIST ER_REORG_PARTITION_DOES_NOT_EXIST
That is longer by the whole useless word...
It correct grammar. Messages looking bad otherwise. Or, better, don't rename error messages at all and preserve the compatibility with older applications. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Sergei,
On Wed, Sep 1, 2021 at 10:20 PM Sergei Golubchik
Hi, Aleksey!
On Sep 01, Aleksey Midenkov wrote:
Looks like IF_DBUG is superfluous macro and should be replaced by
#ifndef DBUG_OFF #endif
No, it's used in expression. Precisely, to avoid ifdefs.
So, what about DBUG(A) variant?
We have IF_XXX for many different XXX. IF_DBUG was created to follow this convention. Anytime you see a macro IF_XXX you know what it does. Let's keep it that way.
We also use DBUG_ prefix for debug things. IF_DBUG() scheme is superfluous as only a1 used in most cases. So if renamed to DBUG_DO() or just to DBUG() the scheme is not broken and the code looks nicer. Please have a glance at the patch attached.
About your ER_KEY_COLUMN_DOES_NOT_EXITS replacement:
$ grep -c DOES_NOT_EXIST sql/share/errmsg-utf8.txt 6 $ grep -c NOT_EXIST sql/share/errmsg-utf8.txt 7
So only one existing error message uses NOT_EXIST without DOES. Let's keep the conventional naming. So, it should be
ER_KEY_DOES_NOT_EXIST ER_KEY_COLUMN_DOES_NOT_EXIST ER_PARTITION_DOES_NOT_EXIST ER_REORG_PARTITION_DOES_NOT_EXIST
That is longer by the whole useless word...
It correct grammar. Messages looking bad otherwise.
But we are talking only about code names and they are not visible to a user, are they? Even SQL itself does use the short form "NOT EXISTS". :) I don't see any problems here.
Or, better, don't rename error messages at all and preserve the compatibility with older applications.
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Sep 01, Aleksey Midenkov wrote:
On Wed, Sep 1, 2021 at 10:20 PM Sergei Golubchik
wrote: On Sep 01, Aleksey Midenkov wrote:
Looks like IF_DBUG is superfluous macro and should be replaced by
#ifndef DBUG_OFF #endif
No, it's used in expression. Precisely, to avoid ifdefs.
So, what about DBUG(A) variant?
We have IF_XXX for many different XXX. IF_DBUG was created to follow this convention. Anytime you see a macro IF_XXX you know what it does. Let's keep it that way.
We also use DBUG_ prefix for debug things. IF_DBUG() scheme is superfluous as only a1 used in most cases. So if renamed to DBUG_DO() or just to DBUG() the scheme is not broken and the code looks nicer. Please have a glance at the patch attached.
I did. I also grepped include/ for IF_[A-Z]+, we have IF_WIN, IF_EMBEDDED, IF_PARTITIONING, IF_WSREP, IF_DBUG, IF_VALGRIND together they're used on 165 lines. It would be very unhelpful, if IF_DBUG would suddenly deviate from this scheme and would become a special exception to remember.
So only one existing error message uses NOT_EXIST without DOES. Let's keep the conventional naming. So, it should be
ER_KEY_DOES_NOT_EXIST ER_KEY_COLUMN_DOES_NOT_EXIST ER_PARTITION_DOES_NOT_EXIST ER_REORG_PARTITION_DOES_NOT_EXIST
That is longer by the whole useless word...
It correct grammar. Messages looking bad otherwise.
But we are talking only about code names and they are not visible to a user, are they? Even SQL itself does use the short form "NOT EXISTS". :)
it's IF NOT EXISTS, but it does indeed. Okay, if you keep backward compatibility defines, you can rename them. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi Sergei!
On Thu, Sep 2, 2021 at 5:13 PM Sergei Golubchik
Hi, Aleksey!
On Sep 01, Aleksey Midenkov wrote:
On Wed, Sep 1, 2021 at 10:20 PM Sergei Golubchik
wrote: On Sep 01, Aleksey Midenkov wrote:
Looks like IF_DBUG is superfluous macro and should be replaced by
#ifndef DBUG_OFF #endif
No, it's used in expression. Precisely, to avoid ifdefs.
So, what about DBUG(A) variant?
We have IF_XXX for many different XXX. IF_DBUG was created to follow this convention. Anytime you see a macro IF_XXX you know what it does. Let's keep it that way.
We also use DBUG_ prefix for debug things. IF_DBUG() scheme is superfluous as only a1 used in most cases. So if renamed to DBUG_DO() or just to DBUG() the scheme is not broken and the code looks nicer. Please have a glance at the patch attached.
I did. I also grepped include/ for IF_[A-Z]+, we have
IF_WIN, IF_EMBEDDED, IF_PARTITIONING, IF_WSREP, IF_DBUG, IF_VALGRIND
together they're used on 165 lines. It would be very unhelpful, if IF_DBUG would suddenly deviate from this scheme and would become a special exception to remember.
Okay, I'm not going to change that. Though IF_DBUG() AFAIR is used naturally only in a couple of lines. The dozen of other IF_DBUG() uses are only with one argument. So, do you still think DBUG_IF() makes confusion with IF_DBUG()?
So only one existing error message uses NOT_EXIST without DOES. Let's keep the conventional naming. So, it should be
ER_KEY_DOES_NOT_EXIST ER_KEY_COLUMN_DOES_NOT_EXIST ER_PARTITION_DOES_NOT_EXIST ER_REORG_PARTITION_DOES_NOT_EXIST
That is longer by the whole useless word...
It correct grammar. Messages looking bad otherwise.
But we are talking only about code names and they are not visible to a user, are they? Even SQL itself does use the short form "NOT EXISTS". :)
it's IF NOT EXISTS, but it does indeed. Okay, if you keep backward compatibility defines, you can rename them.
Updated.
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Sep 06, Aleksey Midenkov wrote:
I did. I also grepped include/ for IF_[A-Z]+, we have
IF_WIN, IF_EMBEDDED, IF_PARTITIONING, IF_WSREP, IF_DBUG, IF_VALGRIND
together they're used on 165 lines. It would be very unhelpful, if IF_DBUG would suddenly deviate from this scheme and would become a special exception to remember.
Okay, I'm not going to change that. Though IF_DBUG() AFAIR is used naturally only in a couple of lines. The dozen of other IF_DBUG() uses are only with one argument.
So, do you still think DBUG_IF() makes confusion with IF_DBUG()?
A bit. It's not a showstopper. I mentioned it as an argument, in case, for example, if you have two almost equally good names, then this argument is against DBUG_IF, so it could help you to prefer the other one. But you can consider this argument and still prefer DBUG_IF. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi, Aleksey! On Aug 26, Sergei Golubchik wrote:
ALTER ... MOVE TABLE table_name TO PARTITION (...) ALTER ... MOVE PARTITION ... TO TABLE table_name
There is no MOVE symbol and we should not add a new one because of the same compatibility reason: it will not be possible to create table "move" (as well as to work with existing one I suspect).
So, yes, I totally agree that it's best to avoid adding new keywords to the grammar.
That's why we found MIGRATE as a good candidate And the reasons to have some special keyword, not just "ADD PARTITION ... FROM ..." are:
If it's my suggested synax from above, but with MIGRATE, it becomes
ALTER TABLE ... MIGRATE TABLE tbl_name TO PARTITION (partition definition) ALTER TABLE ... MIGRATE PARTITION part_name TO TABLE tbl_name
so very symmetrical.
"MIGRATE" is still a bit awkward here, because "migrate" is historically an intransitive verb, it isn't normally used like that. I went over all keywords in lex.h again and I think this one works quite well: ALTER TABLE ... CONVERT TABLE tbl_name TO PARTITION (partition definition) ALTER TABLE ... CONVERT PARTITION part_name TO TABLE tbl_name I also think it conveys the meaning better. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi Sergei!
On Sat, Sep 4, 2021 at 3:34 PM Sergei Golubchik
Hi, Aleksey!
On Aug 26, Sergei Golubchik wrote:
ALTER ... MOVE TABLE table_name TO PARTITION (...) ALTER ... MOVE PARTITION ... TO TABLE table_name
There is no MOVE symbol and we should not add a new one because of the same compatibility reason: it will not be possible to create table "move" (as well as to work with existing one I suspect).
So, yes, I totally agree that it's best to avoid adding new keywords to the grammar.
That's why we found MIGRATE as a good candidate And the reasons to have some special keyword, not just "ADD PARTITION ... FROM ..." are:
If it's my suggested synax from above, but with MIGRATE, it becomes
ALTER TABLE ... MIGRATE TABLE tbl_name TO PARTITION (partition definition) ALTER TABLE ... MIGRATE PARTITION part_name TO TABLE tbl_name
so very symmetrical.
"MIGRATE" is still a bit awkward here, because "migrate" is historically an intransitive verb, it isn't normally used like that.
I went over all keywords in lex.h again and I think this one works quite well:
ALTER TABLE ... CONVERT TABLE tbl_name TO PARTITION (partition definition) ALTER TABLE ... CONVERT PARTITION part_name TO TABLE tbl_name
I also think it conveys the meaning better.
Yes, CONVERT looks more natural. Updated the code.
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Aug 26, Aleksey Midenkov wrote:
Hi Sergei!
The updated branch is cabd0530 bb-10.7-midenok-MDEV-22166
Commits cabd0530426 Parser refactoring db69d4eb025 Cleanups are fine, thanks. The main change in the simplified diff is:
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -1299,7 +1299,7 @@ bool Query_log_event::write() if (thd && thd->binlog_xid) { *start++= Q_XID; - int8store(start, thd->query_id); + int8store(start, thd->binlog_xid);
I agree that it looks correct. How did you find it? Does your patch introduce a case where thd->binlog_xid != thd->query_id ?
start+= 8; }
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -7439,18 +7439,28 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, alter_partition_extract(lpt) || (frm_install= TRUE, FALSE) || mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) || log_partition_alter_to_ddl_log(lpt) || (frm_install= FALSE, FALSE) || + ((!thd->lex->no_write_to_binlog) && + (thd->binlog_xid= thd->query_id, + ddl_log_update_xid(lpt->part_info, thd->binlog_xid), + write_bin_log(thd, false, thd->query(), thd->query_length()), + thd->binlog_xid= 0)) ||
do I understand it correctly - if the crash happens before the binlog write, ddl log on recovery will undo everything. If the crash happens after, it'll see the xid in binlog and will not undo the operation?
+ /* + Note: this crash-point does not cleanup backup (see WFRM_DROP_BACKUP), + but this crash-point is low probability as ddl_log_complete() is + fast operation. + */
I still don't quite understand why did you introduce a new method with frm backup and a (low probability) window where it won't clean up. Isn't it similar to normal ALTER TABLE? It also needs to replace frms and it is solved with ddl log - if a crash happens after the point of no return (after the frm was replaced with a new one), ddl log will binlog the query on recovery. Could you do the same, like case DDL_LOCK_MIGRATE_PARTITION_ACTION: if (shadow frm no longer exists && xid not in binlog) write_bin_log(...); would that work? Or would partitioning-specific old ddl logging code interfere?
(ddl_log_complete(lpt->part_info), false) || - ((!thd->lex->no_write_to_binlog) && - (write_bin_log(thd, FALSE, - thd->query(), thd->query_length()), FALSE)) || mysql_write_frm(lpt, WFRM_DROP_BACKUP) ||
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi Sergei!
On Fri, Aug 27, 2021 at 3:23 PM Sergei Golubchik
Hi, Aleksey!
On Aug 26, Aleksey Midenkov wrote:
Hi Sergei!
The updated branch is cabd0530 bb-10.7-midenok-MDEV-22166
Commits
cabd0530426 Parser refactoring db69d4eb025 Cleanups
are fine, thanks. The main change in the simplified diff is:
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -1299,7 +1299,7 @@ bool Query_log_event::write() if (thd && thd->binlog_xid) { *start++= Q_XID; - int8store(start, thd->query_id); + int8store(start, thd->binlog_xid);
I agree that it looks correct. How did you find it? Does your patch introduce a case where thd->binlog_xid != thd->query_id ?
I just tried to update xid via query_id and failed. The interface of updating xid is quite weird by having to copy query_id to binlog_xid and then clear binlog_xid back. I don't understand why this is needed.
start+= 8; }
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -7439,18 +7439,28 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, alter_partition_extract(lpt) || (frm_install= TRUE, FALSE) || mysql_write_frm(lpt, WFRM_INSTALL_SHADOW|WFRM_BACKUP_ORIGINAL) || log_partition_alter_to_ddl_log(lpt) || (frm_install= FALSE, FALSE) || + ((!thd->lex->no_write_to_binlog) && + (thd->binlog_xid= thd->query_id, + ddl_log_update_xid(lpt->part_info, thd->binlog_xid), + write_bin_log(thd, false, thd->query(), thd->query_length()), + thd->binlog_xid= 0)) ||
do I understand it correctly - if the crash happens before the binlog write, ddl log on recovery will undo everything. If the crash happens after, it'll see the xid in binlog and will not undo the operation?
Yes. Don't forget about error handling. We rollback everything on error, that is important for atomicity too. And that was not done for the main code of mysql_alter_table() AFAIK.
+ /* + Note: this crash-point does not cleanup backup (see WFRM_DROP_BACKUP), + but this crash-point is low probability as ddl_log_complete() is + fast operation. + */
I still don't quite understand why did you introduce a new method with frm backup and a (low probability) window where it won't clean up.
Isn't it similar to normal ALTER TABLE? It also needs to replace frms and it is solved with ddl log - if a crash happens after the point of no return (after the frm was replaced with a new one), ddl log will binlog the query on recovery.
Could you do the same, like
case DDL_LOCK_MIGRATE_PARTITION_ACTION: if (shadow frm no longer exists && xid not in binlog) write_bin_log(...);
would that work? Or would partitioning-specific old ddl logging code interfere?
I believe ALTER TABLE atomicity is not the perfect one in respect of rollback on error so why should that be an example for me? Another issue with the scheme you proposed is worse complexity and reliability. Why do I have to do some vague logic about binlogging if it can be straightforward and simple? So either I have to expand frm handling or add another DDL log action: why are you asking me not to do the former and do the latter? I can create the second chain for cleaning up the leftover backups and that would be anyway better than binlogging in 2 places.
(ddl_log_complete(lpt->part_info), false) || - ((!thd->lex->no_write_to_binlog) && - (write_bin_log(thd, FALSE, - thd->query(), thd->query_length()), FALSE)) || mysql_write_frm(lpt, WFRM_DROP_BACKUP) ||
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Aug 27, Aleksey Midenkov wrote:
I still don't quite understand why did you introduce a new method with frm backup and a (low probability) window where it won't clean up.
Isn't it similar to normal ALTER TABLE? It also needs to replace frms and it is solved with ddl log - if a crash happens after the point of no return (after the frm was replaced with a new one), ddl log will binlog the query on recovery.
Could you do the same, like
case DDL_LOCK_MIGRATE_PARTITION_ACTION: if (shadow frm no longer exists && xid not in binlog) write_bin_log(...);
would that work? Or would partitioning-specific old ddl logging code interfere?
I believe ALTER TABLE atomicity is not the perfect one in respect of rollback on error so why should that be an example for me?
let's start from a statement. You're stating that ALTER TABLE atomicity is not the perfect one in respect of rollback on error. What do you mean by that? Can you show how ALTER TABLE wouldn't be atomic after a rollback on an error?
Another issue with the scheme you proposed is worse complexity and reliability.
It's the scheme that ALTER TABLE and other DDL statements are using now. If you have something simpler and more reliable, could you please describe it so that we could change all DDL statements to use your approach?
Why do I have to do some vague logic about binlogging if it can be straightforward and simple? So either I have to expand frm handling or add another DDL log action: why are you asking me not to do the former and do the latter?
Because - as far as I understand - the latter is what all other DDL statements use, except old partitioning statements that weren't converted yet. we really do not want *three* different approaches to atomicity in the same ALTER TABLE statement. It's just not maintainable. But perhaps I misunderstood and DDL atomicity was implemented differently from what I've described? Then I'm sorry, I didn't intend to suggest that you should implement yet another approach to DDL atomicity, I was saying, please, do what other statements do. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Sergei,
On Wed, Sep 1, 2021 at 8:51 PM Sergei Golubchik
Hi, Aleksey!
On Aug 27, Aleksey Midenkov wrote:
I still don't quite understand why did you introduce a new method with frm backup and a (low probability) window where it won't clean up.
Isn't it similar to normal ALTER TABLE? It also needs to replace frms and it is solved with ddl log - if a crash happens after the point of no return (after the frm was replaced with a new one), ddl log will binlog the query on recovery.
Could you do the same, like
case DDL_LOCK_MIGRATE_PARTITION_ACTION: if (shadow frm no longer exists && xid not in binlog) write_bin_log(...);
would that work? Or would partitioning-specific old ddl logging code interfere?
I believe ALTER TABLE atomicity is not the perfect one in respect of rollback on error so why should that be an example for me?
let's start from a statement. You're stating that ALTER TABLE atomicity is not the perfect one in respect of rollback on error.
What do you mean by that? Can you show how ALTER TABLE wouldn't be atomic after a rollback on an error?
An example test is attached to this email.
Another issue with the scheme you proposed is worse complexity and reliability.
It's the scheme that ALTER TABLE and other DDL statements are using now. If you have something simpler and more reliable, could you please describe it so that we could change all DDL statements to use your approach?
Why do I have to do some vague logic about binlogging if it can be straightforward and simple? So either I have to expand frm handling or add another DDL log action: why are you asking me not to do the former and do the latter?
Because - as far as I understand - the latter is what all other DDL statements use, except old partitioning statements that weren't converted yet.
we really do not want *three* different approaches to atomicity in the same ALTER TABLE statement. It's just not maintainable.
I guess partitioning has no approach for that, the best it does is printing the warning message. So it is 2 of them. And partitioning can be easily switched to my scheme. As for the other DDL, it should be simplified as well, I hope this is possible. But as an intermediate we can have 2 approaches: for partitioning (my scheme) and for other DDL.
But perhaps I misunderstood and DDL atomicity was implemented differently from what I've described? Then I'm sorry, I didn't intend to suggest that you should implement yet another approach to DDL atomicity, I was saying, please, do what other statements do.
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- All the best, Aleksey Midenkov @midenok
Hi, Aleksey! On Sep 06, Aleksey Midenkov wrote:
I believe ALTER TABLE atomicity is not the perfect one in respect of rollback on error so why should that be an example for me?
let's start from a statement. You're stating that ALTER TABLE atomicity is not the perfect one in respect of rollback on error.
What do you mean by that? Can you show how ALTER TABLE wouldn't be atomic after a rollback on an error?
An example test is attached to this email.
Hmm, I see, thanks.
I guess partitioning has no approach for that, the best it does is printing the warning message. So it is 2 of them. And partitioning can be easily switched to my scheme. As for the other DDL, it should be simplified as well, I hope this is possible. But as an intermediate we can have 2 approaches: for partitioning (my scheme) and for other DDL.
Okay, can you push this MDEV into preview-10.7-MDEV-22166-convert-partition ? Only commits related to this MDEV, properly logically squashed, tests fixed. Commits related to CREATE OR REPLACE shouldn't be there. changes to parser.test or any traces of EXTRACT neither. I suspect you broke dbug-t unit test, please, verify that it passes. Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
Hi Sergei,
On Tue, Sep 7, 2021 at 12:34 PM Sergei Golubchik
Hi, Aleksey!
On Sep 06, Aleksey Midenkov wrote:
I believe ALTER TABLE atomicity is not the perfect one in respect of rollback on error so why should that be an example for me?
let's start from a statement. You're stating that ALTER TABLE atomicity is not the perfect one in respect of rollback on error.
What do you mean by that? Can you show how ALTER TABLE wouldn't be atomic after a rollback on an error?
An example test is attached to this email.
Hmm, I see, thanks.
I guess partitioning has no approach for that, the best it does is printing the warning message. So it is 2 of them. And partitioning can be easily switched to my scheme. As for the other DDL, it should be simplified as well, I hope this is possible. But as an intermediate we can have 2 approaches: for partitioning (my scheme) and for other DDL.
Okay, can you push this MDEV into preview-10.7-MDEV-22166-convert-partition ? Only commits related to this MDEV, properly logically squashed, tests fixed. Commits related to CREATE OR REPLACE shouldn't be there. changes to parser.test or any traces of EXTRACT neither. I suspect you broke dbug-t unit test, please, verify that it passes.
Pushed.
Regards, Sergei VP of MariaDB Server Engineering and security@mariadb.org
-- @midenok
participants (2)
-
Aleksey Midenkov
-
Sergei Golubchik