summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/ha_partition.cc150
-rw-r--r--sql/sql_partition.cc177
-rw-r--r--sql/sql_partition.h6
3 files changed, 204 insertions, 129 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index aadac36e2ee..414f9d52536 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -624,7 +624,7 @@ int ha_partition::create(const char *name, TABLE *table_arg,
int ha_partition::drop_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
- char part_name_buff[FN_REFLEN];
+ char part_name_buff[FN_REFLEN + 1];
uint num_parts= m_part_info->partitions.elements;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
@@ -657,9 +657,12 @@ int ha_partition::drop_partitions(const char *path)
{
partition_element *sub_elem= sub_it++;
part= i * num_subparts + j;
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name, name_variant);
+ if ((ret_error= create_subpartition_name(part_name_buff, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ name_variant)))
+ error= ret_error;
+
file= m_file[part];
DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff));
if ((ret_error= file->ha_delete_table(part_name_buff)))
@@ -670,9 +673,11 @@ int ha_partition::drop_partitions(const char *path)
}
else
{
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, name_variant,
- TRUE);
+ if ((ret_error= create_partition_name(part_name_buff, path,
+ part_elem->partition_name,
+ name_variant, TRUE)))
+ error= ret_error;
+
file= m_file[i];
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
if ((ret_error= file->ha_delete_table(part_name_buff)))
@@ -714,8 +719,8 @@ int ha_partition::rename_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
List_iterator<partition_element> temp_it(m_part_info->temp_partitions);
- char part_name_buff[FN_REFLEN];
- char norm_name_buff[FN_REFLEN];
+ char part_name_buff[FN_REFLEN + 1];
+ char norm_name_buff[FN_REFLEN + 1];
uint num_parts= m_part_info->partitions.elements;
uint part_count= 0;
uint num_subparts= m_part_info->num_subparts;
@@ -757,10 +762,11 @@ int ha_partition::rename_partitions(const char *path)
{
sub_elem= sub_it++;
file= m_reorged_file[part_count++];
- create_subpartition_name(norm_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- NORMAL_PART_NAME);
+ if ((ret_error= create_subpartition_name(norm_name_buff, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ NORMAL_PART_NAME)))
+ error= ret_error;
DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
error= ret_error;
@@ -773,9 +779,11 @@ int ha_partition::rename_partitions(const char *path)
else
{
file= m_reorged_file[part_count++];
- create_partition_name(norm_name_buff, path,
- part_elem->partition_name, NORMAL_PART_NAME,
- TRUE);
+ if ((ret_error= create_partition_name(norm_name_buff, path,
+ part_elem->partition_name,
+ NORMAL_PART_NAME, TRUE)))
+ error= ret_error;
+
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->ha_delete_table(norm_name_buff)))
error= ret_error;
@@ -825,10 +833,12 @@ int ha_partition::rename_partitions(const char *path)
{
sub_elem= sub_it++;
part= i * num_subparts + j;
- create_subpartition_name(norm_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- NORMAL_PART_NAME);
+ if ((ret_error= create_subpartition_name(norm_name_buff, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ NORMAL_PART_NAME)))
+ error= ret_error;
+
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
@@ -840,10 +850,12 @@ int ha_partition::rename_partitions(const char *path)
(void) sync_ddl_log();
}
file= m_new_file[part];
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- TEMP_PART_NAME);
+ if ((ret_error= create_subpartition_name(part_name_buff, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ TEMP_PART_NAME)))
+ error= ret_error;
+
DBUG_PRINT("info", ("Rename subpartition from %s to %s",
part_name_buff, norm_name_buff));
if ((ret_error= file->ha_rename_table(part_name_buff,
@@ -857,9 +869,11 @@ int ha_partition::rename_partitions(const char *path)
}
else
{
- create_partition_name(norm_name_buff, path,
- part_elem->partition_name, NORMAL_PART_NAME,
- TRUE);
+ if ((ret_error= create_partition_name(norm_name_buff, path,
+ part_elem->partition_name,
+ NORMAL_PART_NAME, TRUE)))
+ error= ret_error;
+
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
@@ -871,9 +885,11 @@ int ha_partition::rename_partitions(const char *path)
(void) sync_ddl_log();
}
file= m_new_file[i];
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, TEMP_PART_NAME,
- TRUE);
+ if ((ret_error= create_partition_name(part_name_buff, path,
+ part_elem->partition_name,
+ TEMP_PART_NAME, TRUE)))
+ error= ret_error;
+
DBUG_PRINT("info", ("Rename partition from %s to %s",
part_name_buff, norm_name_buff));
if ((ret_error= file->ha_rename_table(part_name_buff,
@@ -1477,7 +1493,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
{
List_iterator<partition_element> part_it(m_part_info->partitions);
List_iterator <partition_element> t_it(m_part_info->temp_partitions);
- char part_name_buff[FN_REFLEN];
+ char part_name_buff[FN_REFLEN + 1];
uint num_parts= m_part_info->partitions.elements;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
@@ -1687,10 +1703,15 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
do
{
partition_element *sub_elem= sub_it++;
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- name_variant);
+ if ((error= create_subpartition_name(part_name_buff, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ name_variant)))
+ {
+ cleanup_new_partition(part_count);
+ DBUG_RETURN(error);
+ }
+
part= i * num_subparts + j;
DBUG_PRINT("info", ("Add subpartition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
@@ -1708,9 +1729,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
}
else
{
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, name_variant,
- TRUE);
+ if ((error= create_partition_name(part_name_buff, path,
+ part_elem->partition_name,
+ name_variant, TRUE)))
+ {
+ cleanup_new_partition(part_count);
+ DBUG_RETURN(error);
+ }
+
DBUG_PRINT("info", ("Add partition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
new_file_array[i],
@@ -1967,8 +1993,8 @@ int ha_partition::del_ren_cre_table(const char *from,
{
int save_error= 0;
int error= HA_ERR_INTERNAL_ERROR;
- char from_buff[FN_REFLEN], to_buff[FN_REFLEN], from_lc_buff[FN_REFLEN],
- to_lc_buff[FN_REFLEN], buff[FN_REFLEN];
+ char from_buff[FN_REFLEN + 1], to_buff[FN_REFLEN + 1], from_lc_buff[FN_REFLEN + 1],
+ to_lc_buff[FN_REFLEN + 1], buff[FN_REFLEN + 1];
char *name_buffer_ptr;
const char *from_path;
const char *to_path= NULL;
@@ -2015,13 +2041,16 @@ int ha_partition::del_ren_cre_table(const char *from,
i= 0;
do
{
- create_partition_name(from_buff, from_path, name_buffer_ptr,
- NORMAL_PART_NAME, FALSE);
+ if ((error= create_partition_name(from_buff, from_path, name_buffer_ptr,
+ NORMAL_PART_NAME, FALSE)))
+ DBUG_RETURN(error);
if (to != NULL)
{ // Rename branch
- create_partition_name(to_buff, to_path, name_buffer_ptr,
- NORMAL_PART_NAME, FALSE);
+ if ((error= create_partition_name(to_buff, to_path, name_buffer_ptr,
+ NORMAL_PART_NAME, FALSE)))
+ DBUG_RETURN(error);
+
error= (*file)->ha_rename_table(from_buff, to_buff);
if (error)
goto rename_error;
@@ -2066,9 +2095,9 @@ create_error:
name_buffer_ptr= m_name_buffer_ptr;
for (abort_file= file, file= m_file; file < abort_file; file++)
{
- create_partition_name(from_buff, from_path, name_buffer_ptr, NORMAL_PART_NAME,
- FALSE);
- (void) (*file)->ha_delete_table((const char*) from_buff);
+ if (!create_partition_name(from_buff, from_path, name_buffer_ptr, NORMAL_PART_NAME,
+ FALSE))
+ (void) (*file)->ha_delete_table((const char*) from_buff);
name_buffer_ptr= strend(name_buffer_ptr) + 1;
}
DBUG_RETURN(error);
@@ -2077,12 +2106,12 @@ rename_error:
for (abort_file= file, file= m_file; file < abort_file; file++)
{
/* Revert the rename, back from 'to' to the original 'from' */
- create_partition_name(from_buff, from_path, name_buffer_ptr,
- NORMAL_PART_NAME, FALSE);
- create_partition_name(to_buff, to_path, name_buffer_ptr,
- NORMAL_PART_NAME, FALSE);
- /* Ignore error here */
- (void) (*file)->ha_rename_table(to_buff, from_buff);
+ if (!create_partition_name(from_buff, from_path, name_buffer_ptr,
+ NORMAL_PART_NAME, FALSE))
+ if (!create_partition_name(to_buff, to_path, name_buffer_ptr,
+ NORMAL_PART_NAME, FALSE))
+ /* Ignore error here */
+ (void) (*file)->ha_rename_table(to_buff, from_buff);
name_buffer_ptr= strend(name_buffer_ptr) + 1;
}
DBUG_RETURN(error);
@@ -2707,7 +2736,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
char *name_buffer_ptr;
int error= HA_ERR_INITIALIZATION;
handler **file;
- char name_buff[FN_REFLEN];
+ char name_buff[FN_REFLEN + 1];
bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE);
ulonglong check_table_flags;
DBUG_ENTER("ha_partition::open");
@@ -2777,8 +2806,10 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
file= m_is_clone_of->m_file;
for (i= 0; i < m_tot_parts; i++)
{
- create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME,
- FALSE);
+ if ((error= create_partition_name(name_buff, name, name_buffer_ptr,
+ NORMAL_PART_NAME, FALSE)))
+ goto err_handler;
+
if (!(m_file[i]= file[i]->clone(name_buff, m_clone_mem_root)))
{
error= HA_ERR_INITIALIZATION;
@@ -2793,8 +2824,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
file= m_file;
do
{
- create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME,
- FALSE);
+ if ((error= create_partition_name(name_buff, name, name_buffer_ptr,
+ NORMAL_PART_NAME, FALSE)))
+ goto err_handler;
if ((error= (*file)->ha_open(table, name_buff, mode, test_if_locked)))
goto err_handler;
m_num_locks+= (*file)->lock_count();
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 5358535e9f9..65d4da0f2f6 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -5958,8 +5958,8 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
DDL_LOG_ENTRY ddl_log_entry;
partition_info *part_info= lpt->part_info;
DDL_LOG_MEMORY_ENTRY *log_entry;
- char tmp_path[FN_REFLEN];
- char normal_path[FN_REFLEN];
+ char tmp_path[FN_REFLEN + 1];
+ char normal_path[FN_REFLEN + 1];
List_iterator<partition_element> part_it(part_info->partitions);
uint temp_partitions= part_info->temp_partitions.elements;
uint num_elements= part_info->partitions.elements;
@@ -5983,14 +5983,18 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
ddl_log_entry.next_entry= *next_entry;
ddl_log_entry.handler_name=
ha_resolve_storage_engine_name(sub_elem->engine_type);
- create_subpartition_name(tmp_path, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- TEMP_PART_NAME);
- create_subpartition_name(normal_path, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- NORMAL_PART_NAME);
+ if (create_subpartition_name(tmp_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ TEMP_PART_NAME))
+ DBUG_RETURN(TRUE);
+
+ if (create_subpartition_name(normal_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ NORMAL_PART_NAME))
+ DBUG_RETURN(TRUE);
+
ddl_log_entry.name= normal_path;
ddl_log_entry.from_name= tmp_path;
if (part_elem->part_state == PART_IS_CHANGED)
@@ -6011,12 +6015,13 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
ddl_log_entry.next_entry= *next_entry;
ddl_log_entry.handler_name=
ha_resolve_storage_engine_name(part_elem->engine_type);
- create_partition_name(tmp_path, path,
- part_elem->partition_name,
- TEMP_PART_NAME, TRUE);
- create_partition_name(normal_path, path,
- part_elem->partition_name,
- NORMAL_PART_NAME, TRUE);
+ if ((create_partition_name(tmp_path, path, part_elem->partition_name,
+ TEMP_PART_NAME, TRUE)) ||
+ (create_partition_name(normal_path, path,
+ part_elem->partition_name,
+ NORMAL_PART_NAME, TRUE)))
+ DBUG_RETURN(TRUE);
+
ddl_log_entry.name= normal_path;
ddl_log_entry.from_name= tmp_path;
if (part_elem->part_state == PART_IS_CHANGED)
@@ -6055,7 +6060,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
DDL_LOG_ENTRY ddl_log_entry;
partition_info *part_info= lpt->part_info;
DDL_LOG_MEMORY_ENTRY *log_entry;
- char tmp_path[FN_LEN];
+ char tmp_path[FN_REFLEN + 1];
List_iterator<partition_element> part_it(part_info->partitions);
List_iterator<partition_element> temp_it(part_info->temp_partitions);
uint num_temp_partitions= part_info->temp_partitions.elements;
@@ -6094,10 +6099,12 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
ddl_log_entry.next_entry= *next_entry;
ddl_log_entry.handler_name=
ha_resolve_storage_engine_name(sub_elem->engine_type);
- create_subpartition_name(tmp_path, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- name_variant);
+ if (create_subpartition_name(tmp_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ name_variant))
+ DBUG_RETURN(TRUE);
+
ddl_log_entry.name= tmp_path;
if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
{
@@ -6113,9 +6120,10 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
ddl_log_entry.next_entry= *next_entry;
ddl_log_entry.handler_name=
ha_resolve_storage_engine_name(part_elem->engine_type);
- create_partition_name(tmp_path, path,
- part_elem->partition_name,
- name_variant, TRUE);
+ if ((create_partition_name(tmp_path, path, part_elem->partition_name,
+ name_variant, TRUE)))
+ DBUG_RETURN(TRUE);
+
ddl_log_entry.name= tmp_path;
if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
{
@@ -8194,29 +8202,28 @@ static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter)
}
-/*
- Create partition names
-
- SYNOPSIS
- create_partition_name()
- out:out Created partition name string
- in1 First part
- in2 Second part
- name_variant Normal, temporary or renamed partition name
-
- RETURN VALUE
- NONE
-
- DESCRIPTION
- This method is used to calculate the partition name, service routine to
- the del_ren_cre_table method.
+/**
+ Create partition names. This method is used to calculate the
+ partition name, service routine to the del_ren_cre_table method.
+ The output buffer size should be FN_REFLEN + 1(terminating '\0').
+
+ @param [out] out Created partition name string
+ @param in1 First part
+ @param in2 Second part
+ @param in3 Third part
+ @param name_variant Normal, temporary or renamed partition name
+ @param translate Flag to determine whether to convert a table name
+ to it its corresponding filename.
+
+ @retval true Error.
+ @retval false Success.
*/
-void create_partition_name(char *out, const char *in1,
+bool create_partition_name(char *out, const char *in1,
const char *in2, uint name_variant,
bool translate)
{
- char transl_part_name[FN_REFLEN];
+ char transl_part_name[FN_REFLEN + 1];
const char *transl_part;
if (translate)
@@ -8226,35 +8233,50 @@ void create_partition_name(char *out, const char *in1,
}
else
transl_part= in2;
+
+ // Check if the path name for partition exceeds maximum path length.
if (name_variant == NORMAL_PART_NAME)
- strxmov(out, in1, "#P#", transl_part, NullS);
+ {
+ if ((strlen(in1) + strlen(transl_part) + 3) > FN_REFLEN)
+ {
+ my_error(ER_PATH_LENGTH, MYF(0), in2);
+ return true;
+ }
+ }
+ else
+ if ((strlen(in1) + strlen(transl_part) + 8) > FN_REFLEN)
+ {
+ my_error(ER_PATH_LENGTH, MYF(0), in2);
+ return true;
+ }
+
+ if (name_variant == NORMAL_PART_NAME)
+ strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, NullS);
else if (name_variant == TEMP_PART_NAME)
- strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS);
+ strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, "#TMP#", NullS);
else if (name_variant == RENAMED_PART_NAME)
- strxmov(out, in1, "#P#", transl_part, "#REN#", NullS);
-}
+ strxnmov(out, FN_REFLEN, in1, "#P#", transl_part, "#REN#", NullS);
+ return false;
+}
-/*
- Create subpartition name
-
- SYNOPSIS
- create_subpartition_name()
- out:out Created partition name string
- in1 First part
- in2 Second part
- in3 Third part
- name_variant Normal, temporary or renamed partition name
-
- RETURN VALUE
- NONE
- DESCRIPTION
- This method is used to calculate the subpartition name, service routine to
- the del_ren_cre_table method.
+/**
+ Create subpartition name. This method is used to calculate the
+ subpartition name, service routine to the del_ren_cre_table method.
+ The output buffer size should be FN_REFLEN + 1(terminating '\0').
+
+ @param [out] out Created partition name string
+ @param in1 First part
+ @param in2 Second part
+ @param in3 Third part
+ @param name_variant Normal, temporary or renamed partition name
+
+ @retval true Error.
+ @retval false Success.
*/
-void create_subpartition_name(char *out, const char *in1,
+bool create_subpartition_name(char *out, const char *in1,
const char *in2, const char *in3,
uint name_variant)
{
@@ -8262,15 +8284,36 @@ void create_subpartition_name(char *out, const char *in1,
tablename_to_filename(in2, transl_part_name, FN_REFLEN);
tablename_to_filename(in3, transl_subpart_name, FN_REFLEN);
+
+ // Check if the path name for subpartition exceeds maximum path length.
+ if (name_variant == NORMAL_PART_NAME)
+ {
+ if ((strlen(in1) + strlen(transl_part_name) +
+ strlen(transl_subpart_name) + 7) > FN_REFLEN)
+ {
+ my_error(ER_PATH_LENGTH, MYF(0), in3);
+ return true;
+ }
+ }
+ else
+ if ((strlen(in1) + strlen(transl_part_name) +
+ strlen(transl_subpart_name) + 12) > FN_REFLEN)
+ {
+ my_error(ER_PATH_LENGTH, MYF(0), in3);
+ return true;
+ }
+
if (name_variant == NORMAL_PART_NAME)
- strxmov(out, in1, "#P#", transl_part_name,
+ strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name,
"#SP#", transl_subpart_name, NullS);
else if (name_variant == TEMP_PART_NAME)
- strxmov(out, in1, "#P#", transl_part_name,
+ strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name,
"#SP#", transl_subpart_name, "#TMP#", NullS);
else if (name_variant == RENAMED_PART_NAME)
- strxmov(out, in1, "#P#", transl_part_name,
+ strxnmov(out, FN_REFLEN, in1, "#P#", transl_part_name,
"#SP#", transl_subpart_name, "#REN#", NullS);
+
+ return false;
}
uint get_partition_field_store_length(Field *field)
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index f232eaa0629..cfaab903f04 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -1,7 +1,7 @@
#ifndef SQL_PARTITION_INCLUDED
#define SQL_PARTITION_INCLUDED
-/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -272,10 +272,10 @@ char *generate_partition_syntax(partition_info *part_info,
const char *current_comment_start);
#endif
-void create_partition_name(char *out, const char *in1,
+bool create_partition_name(char *out, const char *in1,
const char *in2, uint name_variant,
bool translate);
-void create_subpartition_name(char *out, const char *in1,
+bool create_subpartition_name(char *out, const char *in1,
const char *in2, const char *in3,
uint name_variant);