summaryrefslogtreecommitdiff
path: root/sql/unireg.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/unireg.cc')
-rw-r--r--sql/unireg.cc273
1 files changed, 115 insertions, 158 deletions
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 40fde228f80..d019b5f8a75 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -39,7 +39,7 @@
/* threshold for safe_alloca */
#define ALLOCA_THRESHOLD 2048
-static uint pack_keys(uchar *,uint, KEY *, ulong);
+static uint pack_keys(uchar *,uint, KEY *, ulong, uint);
static bool pack_header(THD *, uchar *, List<Create_field> &, HA_CREATE_INFO *,
ulong, handler *);
static bool pack_vcols(String *, List<Create_field> &, List<Virtual_column_info> *);
@@ -72,19 +72,24 @@ static uchar *extra2_write_len(uchar *pos, size_t len)
return pos;
}
+static uchar* extra2_write_str(uchar *pos, const LEX_CSTRING &str)
+{
+ pos= extra2_write_len(pos, str.length);
+ memcpy(pos, str.str, str.length);
+ return pos + str.length;
+}
+
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
- const LEX_CSTRING *str)
+ const LEX_CSTRING &str)
{
*pos++ = type;
- pos= extra2_write_len(pos, str->length);
- memcpy(pos, str->str, str->length);
- return pos + str->length;
+ return extra2_write_str(pos, str);
}
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
- LEX_CUSTRING *str)
+ const LEX_CUSTRING &str)
{
- return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str));
+ return extra2_write(pos, type, *reinterpret_cast<const LEX_CSTRING*>(&str));
}
static uchar *extra2_write_field_properties(uchar *pos,
@@ -106,25 +111,18 @@ static uchar *extra2_write_field_properties(uchar *pos,
return pos;
}
-static const bool ROW_START = true;
-static const bool ROW_END = false;
-
-static inline
-uint16
-vers_get_field(HA_CREATE_INFO *create_info, List<Create_field> &create_fields, bool row_start)
+static uint16
+get_fieldno_by_name(HA_CREATE_INFO *create_info, List<Create_field> &create_fields,
+ const Lex_ident &field_name)
{
- DBUG_ASSERT(create_info->versioned());
-
List_iterator<Create_field> it(create_fields);
Create_field *sql_field = NULL;
- const Lex_ident row_field= row_start ? create_info->vers_info.as_row.start
- : create_info->vers_info.as_row.end;
- DBUG_ASSERT(row_field);
+ DBUG_ASSERT(field_name);
for (unsigned field_no = 0; (sql_field = it++); ++field_no)
{
- if (row_field.streq(sql_field->field_name))
+ if (field_name.streq(sql_field->field_name))
{
DBUG_ASSERT(field_no <= uint16(~0U));
return uint16(field_no);
@@ -149,6 +147,11 @@ bool has_extra2_field_flags(List<Create_field> &create_fields)
return false;
}
+static size_t extra2_str_size(size_t len)
+{
+ return (len > 255 ? 3 : 1) + len;
+}
+
/**
Create a frm (table definition) file
@@ -164,7 +167,7 @@ bool has_extra2_field_flags(List<Create_field> &create_fields)
or null LEX_CUSTRING (str==0) in case of an error.
*/
-LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
+LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
HA_CREATE_INFO *create_info,
List<Create_field> &create_fields,
uint keys, KEY *key_info, handler *db_file)
@@ -176,6 +179,12 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
ulong data_offset;
uint options_len;
uint gis_extra2_len= 0;
+ size_t period_info_len= create_info->period_info.name
+ ? extra2_str_size(create_info->period_info.name.length)
+ + extra2_str_size(create_info->period_info.constr->name.length)
+ + 2 * frm_fieldno_size
+ : 0;
+ uint e_unique_hash_extra_parts= 0;
uchar fileinfo[FRM_HEADER_SIZE],forminfo[FRM_FORMINFO_SIZE];
const partition_info *part_info= IF_PARTITIONING(thd->work_part_info, 0);
bool error;
@@ -238,7 +247,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
DBUG_PRINT("info", ("Options length: %u", options_len));
if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN,
- ER_TOO_LONG_TABLE_COMMENT, table->str))
+ ER_TOO_LONG_TABLE_COMMENT, table.str))
DBUG_RETURN(frm);
/*
If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes,
@@ -272,28 +281,35 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
prepare_frm_header(thd, reclength, fileinfo, create_info, keys, key_info);
/* one byte for a type, one or three for a length */
- size_t extra2_size= 1 + 1 + create_info->tabledef_version.length;
+ size_t extra2_size= 1 + extra2_str_size(create_info->tabledef_version.length);
if (options_len)
- extra2_size+= 1 + (options_len > 255 ? 3 : 1) + options_len;
+ extra2_size+= 1 + extra2_str_size(options_len);
if (part_info)
- extra2_size+= 1 + 1 + hton_name(part_info->default_engine_type)->length;
+ extra2_size+= 1 + extra2_str_size(hton_name(part_info->default_engine_type)->length);
if (gis_extra2_len)
- extra2_size+= 1 + (gis_extra2_len > 255 ? 3 : 1) + gis_extra2_len;
+ extra2_size+= 1 + extra2_str_size(gis_extra2_len);
if (create_info->versioned())
{
- extra2_size+= 1 + 1 + 2 * sizeof(uint16);
+ extra2_size+= 1 + extra2_str_size(2 * frm_fieldno_size);
+ }
+
+ if (create_info->period_info.name)
+ {
+ extra2_size+= 1 + extra2_str_size(period_info_len);
}
bool has_extra2_field_flags_= has_extra2_field_flags(create_fields);
if (has_extra2_field_flags_)
{
- extra2_size+= 1 + (create_fields.elements > 255 ? 3 : 1) +
- create_fields.elements;
+ extra2_size+= 1 + extra2_str_size(create_fields.elements);
}
+ for (i= 0; i < keys; i++)
+ if (key_info[i].algorithm == HA_KEY_ALG_LONG_HASH)
+ e_unique_hash_extra_parts++;
key_buff_length= uint4korr(fileinfo+47);
frm.length= FRM_HEADER_SIZE; // fileinfo;
@@ -313,7 +329,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
if (frm.length > FRM_MAX_SIZE ||
create_info->expression_length > UINT_MAX32)
{
- my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table->str);
+ my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table.str);
DBUG_RETURN(frm);
}
@@ -326,11 +342,11 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
pos = frm_ptr + 64;
compile_time_assert(EXTRA2_TABLEDEF_VERSION != '/');
pos= extra2_write(pos, EXTRA2_TABLEDEF_VERSION,
- &create_info->tabledef_version);
+ create_info->tabledef_version);
if (part_info)
pos= extra2_write(pos, EXTRA2_DEFAULT_PART_ENGINE,
- hton_name(part_info->default_engine_type));
+ *hton_name(part_info->default_engine_type));
if (options_len)
{
@@ -349,14 +365,32 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
}
#endif /*HAVE_SPATIAL*/
+ // PERIOD
+ if (create_info->period_info.is_set())
+ {
+ *pos++= EXTRA2_APPLICATION_TIME_PERIOD;
+ pos= extra2_write_len(pos, period_info_len);
+ pos= extra2_write_str(pos, create_info->period_info.name);
+ pos= extra2_write_str(pos, create_info->period_info.constr->name);
+
+ store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
+ create_info->period_info.period.start));
+ pos+= frm_fieldno_size;
+ store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
+ create_info->period_info.period.end));
+ pos+= frm_fieldno_size;
+ }
+
if (create_info->versioned())
{
*pos++= EXTRA2_PERIOD_FOR_SYSTEM_TIME;
- *pos++= 2 * sizeof(uint16);
- int2store(pos, vers_get_field(create_info, create_fields, ROW_START));
- pos+= sizeof(uint16);
- int2store(pos, vers_get_field(create_info, create_fields, ROW_END));
- pos+= sizeof(uint16);
+ *pos++= 2 * frm_fieldno_size;
+ store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
+ create_info->vers_info.as_row.start));
+ pos+= frm_fieldno_size;
+ store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields,
+ create_info->vers_info.as_row.end));
+ pos+= frm_fieldno_size;
}
if (has_extra2_field_flags_)
@@ -366,13 +400,13 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table,
pos+= 4;
DBUG_ASSERT(pos == frm_ptr + uint2korr(fileinfo+6));
- key_info_length= pack_keys(pos, keys, key_info, data_offset);
+ key_info_length= pack_keys(pos, keys, key_info, data_offset, e_unique_hash_extra_parts);
if (key_info_length > UINT_MAX16)
{
my_printf_error(ER_CANT_CREATE_TABLE,
"Cannot create table %`s: index information is too long. "
"Decrease number of indexes or use shorter index names or shorter comments.",
- MYF(0), table->str);
+ MYF(0), table.str);
goto err;
}
@@ -475,60 +509,10 @@ err:
}
-/**
- Create a frm (table definition) file and the tables
-
- @param thd Thread handler
- @param frm Binary frm image of the table to create
- @param path Name of file (including database, without .frm)
- @param db Data base name
- @param table_name Table name
- @param create_info create info parameters
- @param file Handler to use or NULL if only frm needs to be created
-
- @retval 0 ok
- @retval 1 error
-*/
-
-int rea_create_table(THD *thd, LEX_CUSTRING *frm,
- const char *path, const char *db, const char *table_name,
- HA_CREATE_INFO *create_info, handler *file,
- bool no_ha_create_table)
-{
- DBUG_ENTER("rea_create_table");
-
- if (no_ha_create_table)
- {
- if (writefrm(path, db, table_name, true, frm->str, frm->length))
- goto err_frm;
- }
-
- if (thd->variables.keep_files_on_create)
- create_info->options|= HA_CREATE_KEEP_FILES;
-
- if (file->ha_create_partitioning_metadata(path, NULL, CHF_CREATE_FLAG))
- goto err_part;
-
- if (!no_ha_create_table)
- {
- if (ha_create_table(thd, path, db, table_name, create_info, frm))
- goto err_part;
- }
-
- DBUG_RETURN(0);
-
-err_part:
- file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG);
-err_frm:
- deletefrm(path);
- DBUG_RETURN(1);
-} /* rea_create_table */
-
-
/* Pack keyinfo and keynames to keybuff for save in form-file. */
static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
- ulong data_offset)
+ ulong data_offset, uint e_unique_hash_extra_parts)
{
uint key_parts,length;
uchar *pos, *keyname_pos;
@@ -590,6 +574,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
}
}
+ key_parts+= e_unique_hash_extra_parts;
if (key_count > 127 || key_parts > 127)
{
keybuff[0]= (key_count & 0x7f) | 0x80;
@@ -656,7 +641,7 @@ static bool pack_vcols(String *buf, List<Create_field> &create_fields,
for (uint field_nr=0; (field= it++); field_nr++)
{
- if (field->vcol_info)
+ if (field->vcol_info && field->vcol_info->expr)
if (pack_expression(buf, field->vcol_info, field_nr,
field->vcol_info->stored_in_db
? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL))
@@ -897,32 +882,12 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
while ((field=it++))
{
uint recpos;
- int2store(buff+3, field->length);
/* The +1 is here becasue the col offset in .frm file have offset 1 */
recpos= field->offset+1 + (uint) data_offset;
int3store(buff+5,recpos);
- int2store(buff+8,field->pack_flag);
- buff[10]= (uchar) field->unireg_check;
buff[12]= (uchar) field->interval_id;
- buff[13]= (uchar) field->real_field_type();
- if (field->real_field_type() == MYSQL_TYPE_GEOMETRY)
- {
- buff[11]= 0;
- buff[14]= (uchar) field->geom_type;
-#ifndef HAVE_SPATIAL
- DBUG_ASSERT(0); // Should newer happen
-#endif
- }
- else if (field->charset)
- {
- buff[11]= (uchar) (field->charset->number >> 8);
- buff[14]= (uchar) field->charset->number;
- }
- else
- {
- buff[11]= buff[14]= 0; // Numerical
- }
-
+ buff[13]= (uchar) field->type_handler()->real_field_type();
+ field->type_handler()->Column_definition_attributes_frm_pack(field, buff);
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
@@ -1009,13 +974,36 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
DBUG_RETURN(0);
}
+
+static bool make_empty_rec_store_default(THD *thd, Field *regfield,
+ Virtual_column_info *default_value)
+{
+ if (default_value && !default_value->flags)
+ {
+ Item *expr= default_value->expr;
+ // may be already fixed if ALTER TABLE
+ if (expr->fix_fields_if_needed(thd, &expr))
+ return true;
+ DBUG_ASSERT(expr == default_value->expr); // Should not change
+ if (regfield->make_empty_rec_store_default_value(thd, expr))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str);
+ return true;
+ }
+ return false;
+ }
+ regfield->make_empty_rec_reset(thd);
+ return false;
+}
+
+
/* save an empty record on start of formfile */
static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
List<Create_field> &create_fields,
uint reclength, ulong data_offset)
{
- int error= 0;
+ int error= false;
uint null_count;
uchar *null_pos;
TABLE table;
@@ -1043,24 +1031,19 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
while ((field=it++))
{
+ Record_addr addr(buff + field->offset + data_offset,
+ null_pos + null_count / 8, null_count & 7);
+ Column_definition_attributes tmp(*field);
+ tmp.interval= field->save_interval ?
+ field->save_interval : field->interval;
/* regfield don't have to be deleted as it's allocated on THD::mem_root */
- Field *regfield= make_field(&share, thd->mem_root,
- buff+field->offset + data_offset,
- (uint32)field->length,
- null_pos + null_count / 8,
- null_count & 7,
- field->pack_flag,
- field->type_handler(),
- field->charset,
- field->geom_type, field->srid,
- field->unireg_check,
- field->save_interval ? field->save_interval
- : field->interval,
- &field->field_name,
- field->flags);
+ Field *regfield= tmp.make_field(&share, thd->mem_root, &addr,
+ field->type_handler(),
+ &field->field_name,
+ field->flags);
if (!regfield)
{
- error= 1;
+ error= true;
goto err; // End of memory
}
@@ -1077,36 +1060,10 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
!f_bit_as_char(field->pack_flag))
null_count+= field->length & 7;
- if (field->default_value && !field->default_value->flags &&
- (!(field->flags & BLOB_FLAG) ||
- field->real_field_type() == MYSQL_TYPE_GEOMETRY))
- {
- Item *expr= field->default_value->expr;
- // may be already fixed if ALTER TABLE
- int res= expr->fix_fields_if_needed(thd, &expr);
- if (!res)
- res= expr->save_in_field(regfield, 1);
- if (!res && (field->flags & BLOB_FLAG))
- regfield->reset();
-
- /* If not ok or warning of level 'note' */
- if (res != 0 && res != 3)
- {
- my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str);
- error= 1;
- delete regfield; //To avoid memory leak
- goto err;
- }
- delete regfield; //To avoid memory leak
- }
- else if (regfield->real_type() == MYSQL_TYPE_ENUM &&
- (field->flags & NOT_NULL_FLAG))
- {
- regfield->set_notnull();
- regfield->store((longlong) 1, TRUE);
- }
- else
- regfield->reset();
+ error= make_empty_rec_store_default(thd, regfield, field->default_value);
+ delete regfield; // Avoid memory leaks
+ if (error)
+ goto err;
}
DBUG_ASSERT(data_offset == ((null_count + 7) / 8));