Merge 11.8 into 12.1

This commit is contained in:
Marko Mäkelä 2025-10-09 17:46:33 +03:00
commit d29fb34b83
87 changed files with 735 additions and 631 deletions

View file

@ -57,65 +57,11 @@ static MEM_ROOT mem;
static mysql_rwlock_t THR_LOCK_servers;
static LEX_CSTRING MYSQL_SERVERS_NAME= {STRING_WITH_LEN("servers") };
static const TABLE_FIELD_TYPE servers_table_fields[] =
{
{
{ STRING_WITH_LEN("Server_name") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Host") },
{ STRING_WITH_LEN("varchar(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Db") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Username") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Password") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Port") },
{ STRING_WITH_LEN("int(") },
{NULL, 0}
},
{
{ STRING_WITH_LEN("Socket") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Wrapper") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Owner") },
{ STRING_WITH_LEN("varchar(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Options") },
{ STRING_WITH_LEN("longtext") },
{ STRING_WITH_LEN("utf8mb") }
}
enum servers_fields {
SERVER_NAME_FIELD, HOST_FIELD, DB_FIELD, USERNAME_FIELD, PASSWORD_FIELD,
PORT_FIELD, SOCKET_FIELD, SCHEME_FIELD, OWNER_FIELD,
OPTIONS_FIELD
};
static const TABLE_FIELD_DEF servers_table_def=
{
array_elements(servers_table_fields), servers_table_fields, 0, NULL
};
static Table_check_intact_log_error table_intact;
static bool get_server_from_table_to_cache(TABLE *table);
@ -356,8 +302,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
init_sql_alloc(key_memory_servers, &mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
table->use_all_columns();
if (init_read_record(&read_record_info,thd,table, NULL, NULL,
1,0, FALSE))
if (init_read_record(&read_record_info,thd,table, NULL, NULL, 1,0, FALSE))
DBUG_RETURN(1);
while (!(read_record_info.read_record()))
{
@ -374,6 +319,20 @@ end:
}
static bool servers_table_is_valid(TABLE *table)
{
if (table->s->fields < OPTIONS_FIELD ||
table->s->primary_key == MAX_KEY)
{
my_errno= 1;
my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0),
table->s->db.str, table->s->table_name.str);
return false;
}
return true;
}
/*
Forget current servers cache and read new servers
from the connection table.
@ -417,12 +376,8 @@ bool servers_reload(THD *thd)
goto end;
}
if (table_intact.check(tables.table, &servers_table_def))
{
my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0),
tables.db.str, tables.table_name.str);
if (!servers_table_is_valid(tables.table))
goto end;
}
if ((return_val= servers_load(thd, &tables)))
{ // Error. Revert to old list
@ -516,29 +471,30 @@ get_server_from_table_to_cache(TABLE *table)
DBUG_ENTER("get_server_from_table_to_cache");
/* get each field into the server struct ptr */
ptr= get_field(&mem, table->field[0]);
ptr= get_field(&mem, table->field[SERVER_NAME_FIELD]);
server->server_name= ptr ? ptr : blank;
server->server_name_length= (uint) strlen(server->server_name);
ptr= get_field(&mem, table->field[1]);
ptr= get_field(&mem, table->field[HOST_FIELD]);
server->host= ptr ? ptr : blank;
ptr= get_field(&mem, table->field[2]);
ptr= get_field(&mem, table->field[DB_FIELD]);
server->db= ptr ? ptr : blank;
ptr= get_field(&mem, table->field[3]);
ptr= get_field(&mem, table->field[USERNAME_FIELD]);
server->username= ptr ? ptr : blank;
ptr= get_field(&mem, table->field[4]);
ptr= get_field(&mem, table->field[PASSWORD_FIELD]);
server->password= ptr ? ptr : blank;
ptr= get_field(&mem, table->field[5]);
ptr= get_field(&mem, table->field[PORT_FIELD]);
server->sport= ptr ? ptr : blank;
server->port= server->sport ? atoi(server->sport) : 0;
ptr= get_field(&mem, table->field[6]);
ptr= get_field(&mem, table->field[SOCKET_FIELD]);
server->socket= ptr && strlen(ptr) ? ptr : blank;
ptr= get_field(&mem, table->field[7]);
ptr= get_field(&mem, table->field[SCHEME_FIELD]);
server->scheme= ptr ? ptr : blank;
ptr= get_field(&mem, table->field[8]);
ptr= get_field(&mem, table->field[OWNER_FIELD]);
server->owner= ptr ? ptr : blank;
ptr= table->s->fields > 9 ? get_field(&mem, table->field[9]) : NULL;
ptr= table->s->fields > OPTIONS_FIELD
? get_field(&mem, table->field[OPTIONS_FIELD]) : nullptr;
server->option_list= NULL;
if (ptr && parse_server_options_json(server, ptr))
DBUG_RETURN(TRUE);
@ -588,8 +544,10 @@ insert_server(THD *thd, FOREIGN_SERVER *server)
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_SERVERS_NAME, 0, TL_WRITE);
/* need to open before acquiring THR_LOCK_plugin or it will deadlock */
if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
if (!table || !servers_table_is_valid(table))
goto end;
table->file->row_logging= 0; // Don't log to binary log
/* insert the server into the table */
@ -668,9 +626,6 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server)
table->use_all_columns();
if (table->s->fields < 9)
return ER_CANT_FIND_SYSTEM_REC;
/*
"server" has already been prepped by prepare_server_struct_for_<>
so, all we need to do is check if the value is set (> -1 for port)
@ -680,39 +635,48 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server)
even if with empty strings
*/
if (server->host &&
table->field[1]->store(server->host,
table->field[HOST_FIELD]->store(server->host,
(uint) strlen(server->host), system_charset_info))
goto err;
if (server->db &&
table->field[2]->store(server->db,
table->field[DB_FIELD]->store(server->db,
(uint) strlen(server->db), system_charset_info))
goto err;
if (server->username &&
table->field[3]->store(server->username,
table->field[USERNAME_FIELD]->store(server->username,
(uint) strlen(server->username), system_charset_info))
goto err;
if (server->password &&
table->field[4]->store(server->password,
table->field[PASSWORD_FIELD]->store(server->password,
(uint) strlen(server->password), system_charset_info))
goto err;
if (server->port > -1 &&
table->field[5]->store(server->port))
table->field[PORT_FIELD]->store(server->port))
goto err;
if (server->socket &&
table->field[6]->store(server->socket,
table->field[SOCKET_FIELD]->store(server->socket,
(uint) strlen(server->socket), system_charset_info))
goto err;
if (server->scheme &&
table->field[7]->store(server->scheme,
table->field[SCHEME_FIELD]->store(server->scheme,
(uint) strlen(server->scheme), system_charset_info))
goto err;
if (server->owner &&
table->field[8]->store(server->owner,
table->field[OWNER_FIELD]->store(server->owner,
(uint) strlen(server->owner), system_charset_info))
goto err;
if (table->s->fields <= OPTIONS_FIELD)
{
my_errno= 1;
my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0),
table->s->db.str, table->s->table_name.str);
}
else
{
engine_option_value *option= server->option_list;
StringBuffer<1024> json(table->field[9]->charset());
Field* options_field{table->field[OPTIONS_FIELD]};
StringBuffer<1024> json(options_field->charset());
json.append('{');
while (option)
{
@ -734,7 +698,7 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server)
if (server->option_list)
json.length(json.length() - 2);
json.append('}');
if (!table->field[9]->store(json.ptr(), json.length(), system_charset_info))
if (!options_field->store(json.ptr(), json.length(), system_charset_info))
return 0;
}
@ -778,17 +742,14 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
empty_record(table);
/* set the field that's the PK to the value we're looking for */
table->field[0]->store(server->server_name,
server->server_name_length,
system_charset_info);
table->field[SERVER_NAME_FIELD]->store(server->server_name,
server->server_name_length,
system_charset_info);
/* read index until record is that specified in server_name */
if (unlikely((error=
table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[0]->
ptr,
HA_WHOLE_KEY,
HA_READ_KEY_EXACT))))
if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[SERVER_NAME_FIELD]->ptr,
HA_WHOLE_KEY, HA_READ_KEY_EXACT)))
{
/* if not found, err */
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@ -849,8 +810,8 @@ static int drop_server_internal(THD *thd, LEX_SERVER_OPTIONS *server_options)
if (unlikely((error= delete_server_record_in_cache(server_options))))
goto end;
if (unlikely(!(table= open_ltable(thd, &tables, TL_WRITE,
MYSQL_LOCK_IGNORE_TIMEOUT))))
table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
if (!table || !servers_table_is_valid(table))
{
error= my_errno;
goto end;
@ -977,7 +938,8 @@ int update_server(THD *thd, FOREIGN_SERVER *existing, FOREIGN_SERVER *altered)
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_SERVERS_NAME, 0, TL_WRITE);
if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
if (!table || !servers_table_is_valid(table))
{
error= my_errno;
goto end;
@ -1128,9 +1090,9 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
table->use_all_columns();
/* set the field that's the PK to the value we're looking for */
if (table->field[0]->store(server->server_name,
server->server_name_length,
system_charset_info))
if (table->field[SERVER_NAME_FIELD]->store(server->server_name,
server->server_name_length,
system_charset_info))
{
DBUG_ASSERT(0); /* Protected by servers_cache */
THD *thd= table->in_use;
@ -1138,12 +1100,9 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
return thd->get_stmt_da()->get_sql_errno();
}
if (unlikely((error=
table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[0]->
ptr,
~(longlong)0,
HA_READ_KEY_EXACT))))
if ((error=table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[SERVER_NAME_FIELD]->ptr,
~(longlong)0, HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
table->file->print_error(error, MYF(0));
@ -1197,14 +1156,11 @@ delete_server_record(TABLE *table, LEX_CSTRING *name)
table->use_all_columns();
/* set the field that's the PK to the value we're looking for */
table->field[0]->store(name->str, name->length, system_charset_info);
table->field[SERVER_NAME_FIELD]->store(name->str, name->length, system_charset_info);
if (unlikely((error=
table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[0]->
ptr,
HA_WHOLE_KEY,
HA_READ_KEY_EXACT))))
if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[SERVER_NAME_FIELD]->ptr,
HA_WHOLE_KEY, HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
table->file->print_error(error, MYF(0));
@ -1283,13 +1239,22 @@ end:
mysql_rwlock_unlock(&THR_LOCK_servers);
if (unlikely(error))
{
DBUG_PRINT("info", ("problem creating server <%s>",
server_options->server_name.str));
DBUG_PRINT("info", ("problem creating server <%s>: %d",
server_options->server_name.str, error));
switch (error) {
case 0:
my_ok(thd);
break;
case ER_CANNOT_LOAD_FROM_TABLE_V2:
my_error(error, MYF(0), "mysql", MYSQL_SERVERS_NAME.str);
break;
default:
assert(error == ER_FOREIGN_SERVER_EXISTS);
/* fall through */
case -1: case 1: case ER_OUT_OF_RESOURCES:
my_error(error, MYF(0), server_options->server_name.str);
}
else
my_ok(thd);
DBUG_RETURN(error);
}