Skip to content

Commit f2adb04

Browse files
committed
Bug#27309072: Need a stable api for handling dd::properties.
This patch does some refactoring of the dd::Properties interface and implementation, and introduces a way of defining which keys are valid for a given Property object. Upon the definition of such a set, the validity of the keys will be checked upon setting or getting the value of the key. In more detail, the patch implements the following: 1. Change iterator type names to conform to STL, thus allowing e.g. range based loops. 2. Remove the type specific get()/set() functions and introduce templates and overloads instead. 3. Make all get() variants work in the same way regarding non-existing keys: Assert in debug builds, return 'true' in non-debug builds. Previously, the behavior was not uniform. 4. Remove the value() methods, support only get() instead. 5. Embed the std::map into the Properties_impl class directly without using a unique_ptr. 6. Add a std::set to Properties_impl for storing valid key names. 7. When calling the set() and get() variants, verify that the submitted key is valid, unless the set of valid keys is empty. If the key is invalid, write a warning to the error log, assert in debug builds, return 'true' to the caller in release builds. Note that an error is not reported here, just written to the error log. It is up to the caller to decide how to handle this. 8. Filter out any invalid keys when generating a raw string. This might be relevant in e.g. an upgrade/downgrade situation. 9. Filter out invalid keys when assignning from another property object or from a raw string, using the copy_values() methods. This is done silently without error reporting or asserts, since it is likely to happen e.g. when reading persistent meta data in an upgrade/downgrade situation. Note that copy_values() will copy only the key-value pairs, the set of valid keys in the source object are not copied. 10. In the DD objects using Properties, we now embed the property objects as proper data members instead of using a unique_ptr. This also makes object cloning simpler. 11. There is no custom copy constructor, the default will apply, and this will copy both the set of valid keys and the key-value pairs themselves. Sets of valid keys are added for the Properties that are currently used by the DD object classes, i.e.: dd::Abstract_table_impl::m_options dd::Column_impl::m_options dd::Column_impl::m_se_private_data dd::Index_impl::m_options dd::Index_impl::m_se_private_data dd::Parameter_impl::m_options dd::Partition_impl::m_options dd::Partition_impl::m_se_private_data dd::Partition_index_impl::m_se_private_data dd::Tablespace_impl::m_options dd::Tablespace_impl::m_se_private_data dd::Table_impl::m_se_private_data The infrastructure implemented in this patch also allows similar sets of valid keys to be collected and defined for other classes making use of the dd::Properties implementation. Change-Id: I9c80cc3cbea1fb00bf5b96be77b8ebf471954f23
1 parent 37aae86 commit f2adb04

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1651
-1681
lines changed

share/errmsg-utf8.txt

+3
Original file line numberDiff line numberDiff line change
@@ -18728,6 +18728,9 @@ ER_GEOMETRY_IN_UNKNOWN_LENGTH_UNIT SU001
1872818728
ER_WARN_PROPERTY_STRING_PARSE_FAILED
1872918729
eng "Could not parse key-value pairs in property string '%s'"
1873018730

18731+
ER_INVALID_PROPERTY_KEY
18732+
eng "Property key '%s' is invalid."
18733+
1873118734
#
1873218735
# End of 8.0 error messages intended to be logged to the server error log.
1873318736
#

sql/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ SET(DD_SOURCES
8686
dd/dd_tablespace.cc
8787
dd/dd_trigger.cc
8888
dd/dd_view.cc
89+
dd/properties.cc
8990

9091
dd/impl/bootstrap_ctx.cc
9192
dd/impl/bootstrapper.cc

sql/dd/dd_routine.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ static void fill_parameter_info_from_field(THD *thd, Create_field *field,
193193
// Set geometry sub type
194194
if (field->sql_type == MYSQL_TYPE_GEOMETRY) {
195195
Properties *param_options = &param->options();
196-
param_options->set_uint32("geom_type", field->geom_type);
196+
param_options->set("geom_type", field->geom_type);
197197
}
198198

199199
// Set elements of enum or set data type.

sql/dd/dd_table.cc

+57-56
Original file line numberDiff line numberDiff line change
@@ -675,21 +675,21 @@ bool fill_dd_columns_from_create_fields(THD *thd, dd::Abstract_table *tab_obj,
675675
to handle correctly columns which were created before this change.
676676
*/
677677
if (field->sql_type == MYSQL_TYPE_BIT)
678-
col_options->set_bool("treat_bit_as_char", field->treat_bit_as_char);
678+
col_options->set("treat_bit_as_char", field->treat_bit_as_char);
679679

680680
// Store geometry sub type
681681
if (field->sql_type == MYSQL_TYPE_GEOMETRY) {
682-
col_options->set_uint32("geom_type", field->geom_type);
682+
col_options->set("geom_type", field->geom_type);
683683
}
684684

685685
// Field storage media and column format options
686686
if (field->field_storage_type() != HA_SM_DEFAULT)
687-
col_options->set_uint32("storage",
688-
static_cast<uint32>(field->field_storage_type()));
687+
col_options->set("storage",
688+
static_cast<uint32>(field->field_storage_type()));
689689

690690
if (field->column_format() != COLUMN_FORMAT_TYPE_DEFAULT)
691-
col_options->set_uint32("column_format",
692-
static_cast<uint32>(field->column_format()));
691+
col_options->set("column_format",
692+
static_cast<uint32>(field->column_format()));
693693

694694
//
695695
// Write intervals
@@ -722,11 +722,11 @@ bool fill_dd_columns_from_create_fields(THD *thd, dd::Abstract_table *tab_obj,
722722
col_obj->set_column_type_utf8(get_sql_type_by_create_field(&table, field));
723723

724724
// Store element count in dd::Column
725-
col_options->set_uint32("interval_count", i);
725+
col_options->set("interval_count", i);
726726

727727
// Store geometry sub type
728728
if (field->sql_type == MYSQL_TYPE_GEOMETRY) {
729-
col_options->set_uint32("geom_type", field->geom_type);
729+
col_options->set("geom_type", field->geom_type);
730730
}
731731

732732
// Reset the buffer and assign the column's default value.
@@ -1065,10 +1065,10 @@ static void fill_dd_indexes_from_keyinfo(
10651065
in DD in order to avoid problems with binary compatibility if we decide
10661066
to change conditions in which optimization is applied in future releases.
10671067
*/
1068-
idx_options->set_uint32("flags",
1069-
(key->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY)));
1068+
idx_options->set("flags",
1069+
(key->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY)));
10701070

1071-
if (key->block_size) idx_options->set_uint32("block_size", key->block_size);
1071+
if (key->block_size) idx_options->set("block_size", key->block_size);
10721072

10731073
if (key->parser_name.str)
10741074
idx_options->set("parser_name", key->parser_name.str);
@@ -1276,7 +1276,7 @@ static bool fill_dd_tablespace_id_or_name(THD *thd, T *obj, handlerton *hton,
12761276
This is required in order for SHOW CREATE and CREATE LIKE to ignore
12771277
implicitly assumed tablespace, e.g., 'innodb_system'
12781278
*/
1279-
options->set_bool("explicit_tablespace", true);
1279+
options->set("explicit_tablespace", true);
12801280

12811281
DBUG_RETURN(false);
12821282
}
@@ -1308,15 +1308,15 @@ static bool get_field_list_str(dd::String_type &str, List<char> *name_list) {
13081308
static void set_partition_options(partition_element *part_elem,
13091309
dd::Properties *part_options) {
13101310
if (part_elem->part_max_rows)
1311-
part_options->set_uint64("max_rows", part_elem->part_max_rows);
1311+
part_options->set("max_rows", part_elem->part_max_rows);
13121312
if (part_elem->part_min_rows)
1313-
part_options->set_uint64("min_rows", part_elem->part_min_rows);
1313+
part_options->set("min_rows", part_elem->part_min_rows);
13141314
if (part_elem->data_file_name && part_elem->data_file_name[0])
13151315
part_options->set("data_file_name", part_elem->data_file_name);
13161316
if (part_elem->index_file_name && part_elem->index_file_name[0])
13171317
part_options->set("index_file_name", part_elem->index_file_name);
13181318
if (part_elem->nodegroup_id != UNDEF_NODEGROUP)
1319-
part_options->set_uint32("nodegroup_id", part_elem->nodegroup_id);
1319+
part_options->set("nodegroup_id", part_elem->nodegroup_id);
13201320
}
13211321

13221322
/*
@@ -1620,10 +1620,10 @@ static bool fill_dd_partition_from_create_info(
16201620
} else {
16211621
if (part_elem->signed_flag) {
16221622
val_obj->set_value_utf8(
1623-
dd::Properties::from_int64(part_elem->range_value));
1623+
dd::Properties::to_str(part_elem->range_value));
16241624
} else {
1625-
val_obj->set_value_utf8(dd::Properties::from_uint64(
1626-
(ulonglong)part_elem->range_value));
1625+
val_obj->set_value_utf8(
1626+
dd::Properties::to_str((ulonglong)part_elem->range_value));
16271627
}
16281628
}
16291629

@@ -1672,11 +1672,11 @@ static bool fill_dd_partition_from_create_info(
16721672
val_obj->set_list_num(list_index);
16731673
if (list_value->unsigned_flag) {
16741674
val_obj->set_value_utf8(
1675-
dd::Properties::from_uint64((ulonglong)list_value->value));
1675+
dd::Properties::to_str((ulonglong)list_value->value));
16761676
part_desc_res.set((ulonglong)list_value->value, cs);
16771677
} else {
16781678
val_obj->set_value_utf8(
1679-
dd::Properties::from_int64(list_value->value));
1679+
dd::Properties::to_str(list_value->value));
16801680
part_desc_res.set(list_value->value, cs);
16811681
}
16821682
part_desc_str.append(part_desc_res);
@@ -1920,10 +1920,10 @@ static bool fill_dd_table_from_create_info(
19201920
dd::Properties *table_options = &tab_obj->options();
19211921

19221922
if (create_info->max_rows)
1923-
table_options->set_uint64("max_rows", create_info->max_rows);
1923+
table_options->set("max_rows", create_info->max_rows);
19241924

19251925
if (create_info->min_rows)
1926-
table_options->set_uint64("min_rows", create_info->min_rows);
1926+
table_options->set("min_rows", create_info->min_rows);
19271927

19281928
//
19291929
// Options encoded in HA_CREATE_INFO::table_options.
@@ -1945,8 +1945,8 @@ static bool fill_dd_table_from_create_info(
19451945
problems with binary compatibility if we decide to change rules for
19461946
applying this optimization in future releases.
19471947
*/
1948-
table_options->set_bool("pack_record",
1949-
create_info->table_options & HA_OPTION_PACK_RECORD);
1948+
table_options->set("pack_record",
1949+
create_info->table_options & HA_OPTION_PACK_RECORD);
19501950

19511951
/*
19521952
PACK_KEYS=# clause. Absence of PACK_KEYS option/PACK_KEYS=DEFAULT is
@@ -1958,8 +1958,8 @@ static bool fill_dd_table_from_create_info(
19581958
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) !=
19591959
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS));
19601960

1961-
table_options->set_bool("pack_keys",
1962-
create_info->table_options & HA_OPTION_PACK_KEYS);
1961+
table_options->set("pack_keys",
1962+
create_info->table_options & HA_OPTION_PACK_KEYS);
19631963
}
19641964

19651965
/*
@@ -1969,16 +1969,16 @@ static bool fill_dd_table_from_create_info(
19691969
DBUG_ASSERT(!((create_info->table_options & HA_OPTION_CHECKSUM) &&
19701970
(create_info->table_options & HA_OPTION_NO_CHECKSUM)));
19711971
if (create_info->table_options & (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
1972-
table_options->set_bool("checksum",
1973-
create_info->table_options & HA_OPTION_CHECKSUM);
1972+
table_options->set("checksum",
1973+
create_info->table_options & HA_OPTION_CHECKSUM);
19741974

19751975
/* DELAY_KEY_WRITE=# clause. Same situation as for CHECKSUM option. */
19761976
DBUG_ASSERT(!((create_info->table_options & HA_OPTION_DELAY_KEY_WRITE) &&
19771977
(create_info->table_options & HA_OPTION_NO_DELAY_KEY_WRITE)));
19781978
if (create_info->table_options &
19791979
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
1980-
table_options->set_bool("delay_key_write", create_info->table_options &
1981-
HA_OPTION_DELAY_KEY_WRITE);
1980+
table_options->set("delay_key_write",
1981+
create_info->table_options & HA_OPTION_DELAY_KEY_WRITE);
19821982

19831983
/*
19841984
STATS_PERSISTENT=# clause. Absence option in dd::Properties represents
@@ -1992,35 +1992,34 @@ static bool fill_dd_table_from_create_info(
19921992
(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) !=
19931993
(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT));
19941994

1995-
table_options->set_bool("stats_persistent", (create_info->table_options &
1996-
HA_OPTION_STATS_PERSISTENT));
1995+
table_options->set("stats_persistent", (create_info->table_options &
1996+
HA_OPTION_STATS_PERSISTENT));
19971997
}
19981998

19991999
//
20002000
// Set other table options.
20012001
//
20022002

2003-
table_options->set_uint32("avg_row_length", create_info->avg_row_length);
2003+
table_options->set("avg_row_length", create_info->avg_row_length);
20042004

20052005
if (create_info->row_type != ROW_TYPE_DEFAULT)
2006-
table_options->set_uint32("row_type", create_info->row_type);
2006+
table_options->set("row_type", create_info->row_type);
20072007

20082008
// ROW_FORMAT which was explicitly specified by user (if any).
20092009
if (create_info->row_type != ROW_TYPE_DEFAULT)
2010-
table_options->set_uint32("row_type",
2011-
dd_get_new_row_format(create_info->row_type));
2010+
table_options->set("row_type",
2011+
dd_get_new_row_format(create_info->row_type));
20122012

20132013
// ROW_FORMAT which is really used for the table by SE (perhaps implicitly).
20142014
tab_obj->set_row_format(
20152015
dd_get_new_row_format(file->get_real_row_type(create_info)));
20162016

2017-
table_options->set_uint32("stats_sample_pages",
2018-
create_info->stats_sample_pages & 0xffff);
2017+
table_options->set("stats_sample_pages",
2018+
create_info->stats_sample_pages & 0xffff);
20192019

2020-
table_options->set_uint32("stats_auto_recalc",
2021-
create_info->stats_auto_recalc);
2020+
table_options->set("stats_auto_recalc", create_info->stats_auto_recalc);
20222021

2023-
table_options->set_uint32("key_block_size", create_info->key_block_size);
2022+
table_options->set("key_block_size", create_info->key_block_size);
20242023

20252024
if (create_info->connect_string.str && create_info->connect_string.length) {
20262025
dd::String_type connect_string;
@@ -2043,11 +2042,11 @@ static bool fill_dd_table_from_create_info(
20432042
}
20442043
// Storage media
20452044
if (create_info->storage_media > HA_SM_DEFAULT)
2046-
table_options->set_uint32("storage", create_info->storage_media);
2045+
table_options->set("storage", create_info->storage_media);
20472046

20482047
// Update option keys_disabled
2049-
table_options->set_uint32("keys_disabled",
2050-
(keys_onoff == Alter_info::DISABLE ? 1 : 0));
2048+
table_options->set("keys_disabled",
2049+
(keys_onoff == Alter_info::DISABLE ? 1 : 0));
20512050

20522051
// Collation ID
20532052
DBUG_ASSERT(create_info->default_table_charset);
@@ -2140,7 +2139,7 @@ static bool get_se_private_data(THD *thd, dd::Table *tab_obj) {
21402139
String_type tbl_prop_str;
21412140
if (dd::tables::DD_properties::instance().get(thd, "SYSTEM_TABLES",
21422141
&sys_tbl_props, &exists) ||
2143-
!exists || sys_tbl_props->get(tab_obj->name(), tbl_prop_str)) {
2142+
!exists || sys_tbl_props->get(tab_obj->name(), &tbl_prop_str)) {
21442143
my_error(ER_DD_METADATA_NOT_FOUND, MYF(0), tab_obj->name().c_str());
21452144
return true;
21462145
}
@@ -2151,31 +2150,31 @@ static bool get_se_private_data(THD *thd, dd::Table *tab_obj) {
21512150
Object_id space_id = INVALID_OBJECT_ID;
21522151
String_type se_data;
21532152

2154-
if (tbl_props->get_uint64(
2155-
DD_properties::dd_key(DD_properties::DD_property::ID), &se_id) ||
2156-
tbl_props->get_uint64(
2153+
if (tbl_props->get(DD_properties::dd_key(DD_properties::DD_property::ID),
2154+
&se_id) ||
2155+
tbl_props->get(
21572156
DD_properties::dd_key(DD_properties::DD_property::SPACE_ID),
21582157
&space_id) ||
21592158
tbl_props->get(DD_properties::dd_key(DD_properties::DD_property::DATA),
2160-
se_data)) {
2159+
&se_data)) {
21612160
my_error(ER_DD_METADATA_NOT_FOUND, MYF(0), tab_obj->name().c_str());
21622161
return true;
21632162
}
21642163

21652164
tab_obj->set_se_private_id(se_id);
21662165
tab_obj->set_tablespace_id(space_id);
2167-
tab_obj->set_se_private_data_raw(se_data);
2166+
tab_obj->set_se_private_data(se_data);
21682167

21692168
// Assign SE private data for indexes.
21702169
int count = 0;
21712170
for (auto idx : *tab_obj->indexes()) {
21722171
std::stringstream ss;
21732172
ss << DD_properties::dd_key(DD_properties::DD_property::IDX) << count++;
2174-
if (tbl_props->get(ss.str().c_str(), se_data)) {
2173+
if (tbl_props->get(ss.str().c_str(), &se_data)) {
21752174
my_error(ER_DD_METADATA_NOT_FOUND, MYF(0), tab_obj->name().c_str());
21762175
return true;
21772176
}
2178-
idx->set_se_private_data_raw(se_data);
2177+
idx->set_se_private_data(se_data);
21792178
// Assign the same tablespace id for the indexes as for the table.
21802179
idx->set_tablespace_id(space_id);
21812180
}
@@ -2185,11 +2184,11 @@ static bool get_se_private_data(THD *thd, dd::Table *tab_obj) {
21852184
for (auto col : *tab_obj->columns()) {
21862185
std::stringstream ss;
21872186
ss << DD_properties::dd_key(DD_properties::DD_property::COL) << count++;
2188-
if (tbl_props->get(ss.str().c_str(), se_data)) {
2187+
if (tbl_props->get(ss.str().c_str(), &se_data)) {
21892188
my_error(ER_DD_METADATA_NOT_FOUND, MYF(0), tab_obj->name().c_str());
21902189
return true;
21912190
}
2192-
col->set_se_private_data_raw(se_data);
2191+
col->set_se_private_data(se_data);
21932192
}
21942193
return false;
21952194
}
@@ -2593,7 +2592,8 @@ static void copy_tablespace_ids(const Table &t, IT it) {
25932592
*/
25942593
Encrypt_result is_tablespace_encrypted(THD *thd, const Table &t) {
25952594
if (t.options().exists("encrypt_type")) {
2596-
const String_type &et = t.options().value("encrypt_type");
2595+
String_type et;
2596+
(void)t.options().get("encrypt_type", &et);
25972597
DBUG_ASSERT(et.empty() == false);
25982598
if (et == "Y" || et == "y") {
25992599
return {false, true};
@@ -2626,7 +2626,8 @@ Encrypt_result is_tablespace_encrypted(THD *thd, const Table &t) {
26262626
return false;
26272627
}
26282628

2629-
const String_type &e = tsp->options().value("encryption");
2629+
String_type e;
2630+
(void)tsp->options().get("encryption", &e);
26302631
DBUG_ASSERT(e.empty() == false);
26312632
if (e == "Y" || e == "y") {
26322633
return true;

sql/dd/dd_tablespace.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ bool get_tablespace_name(THD *thd, const T *obj, const char **tablespace_name,
181181
If user has specified special tablespace name like
182182
'innodb_file_per_table' then we read it from tablespace options.
183183
*/
184-
const dd::Properties *table_options = &obj->options();
185-
table_options->get("tablespace", name);
184+
if (obj->options().exists("tablespace"))
185+
(void)obj->options().get("tablespace", &name);
186186
}
187187

188188
*tablespace_name = NULL;

sql/dd/dd_view.cc

+10-6
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,12 @@ static bool fill_dd_view_columns(THD *thd, View *view_obj,
339339
if (!names_dict.empty()) // Explicit names were provided
340340
{
341341
std::string i_s = std::to_string(i);
342-
String_type value = names_dict.value(String_type(i_s.begin(), i_s.end()));
343-
char *name = static_cast<char *>(
344-
strmake_root(thd->mem_root, value.c_str(), value.length()));
342+
String_type value;
343+
char *name = nullptr;
344+
if (!names_dict.get(String_type(i_s.begin(), i_s.end()), &value)) {
345+
name = static_cast<char *>(
346+
strmake_root(thd->mem_root, value.c_str(), value.length()));
347+
}
345348
if (!name) DBUG_RETURN(true); /* purecov: inspected */
346349
cr_field->field_name = name;
347350
}
@@ -564,7 +567,7 @@ static bool fill_dd_view_definition(THD *thd, View *view_obj,
564567
dd::Properties *view_options = &view_obj->options();
565568
view_options->set("timestamp",
566569
String_type(view->timestamp.str, view->timestamp.length));
567-
view_options->set_bool("view_valid", true);
570+
view_options->set("view_valid", true);
568571

569572
// Fill view columns information in View object.
570573
if (fill_dd_view_columns(thd, view_obj, view)) return true;
@@ -686,7 +689,8 @@ bool read_view(TABLE_LIST *view, const dd::View &view_obj, MEM_ROOT *mem_root) {
686689
std::string i_s = std::to_string(++i);
687690
String_type key(i_s.begin(), i_s.end());
688691
if (!names_dict.exists(key)) break;
689-
String_type value = names_dict.value(key);
692+
String_type value;
693+
names_dict.get(key, &value);
690694
char *name = static_cast<char *>(
691695
strmake_root(mem_root, value.c_str(), value.length()));
692696
if (!name || (names_array->push_back({name, value.length()})))
@@ -709,7 +713,7 @@ bool update_view_status(THD *thd, const char *schema_name,
709713

710714
// Update view error status.
711715
dd::Properties *view_options = &new_view->options();
712-
view_options->set_bool("view_valid", status);
716+
view_options->set("view_valid", status);
713717

714718
Disable_gtid_state_update_guard disabler(thd);
715719

0 commit comments

Comments
 (0)