summaryrefslogtreecommitdiff
path: root/sql/unireg.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/unireg.cc')
-rw-r--r--sql/unireg.cc170
1 files changed, 130 insertions, 40 deletions
diff --git a/sql/unireg.cc b/sql/unireg.cc
index ff2b406350a..6540e11578b 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -25,7 +25,7 @@
str is a (long) to record position where 0 is the first position.
*/
-#include <my_global.h>
+#include "mariadb.h"
#include "sql_priv.h"
#include "unireg.h"
#include "sql_partition.h" // struct partition_info
@@ -73,7 +73,7 @@ static uchar *extra2_write_len(uchar *pos, size_t len)
}
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
- LEX_STRING *str)
+ const LEX_CSTRING *str)
{
*pos++ = type;
pos= extra2_write_len(pos, str->length);
@@ -84,10 +84,72 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
LEX_CUSTRING *str)
{
- return extra2_write(pos, type, reinterpret_cast<LEX_STRING *>(str));
+ return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str));
}
-/*
+static uchar *extra2_write_field_properties(uchar *pos,
+ List<Create_field> &create_fields)
+{
+ List_iterator<Create_field> it(create_fields);
+ *pos++= EXTRA2_FIELD_FLAGS;
+ /*
+ always first 2 for field visibility
+ */
+ pos= extra2_write_len(pos, create_fields.elements);
+ while (Create_field *cf= it++)
+ {
+ uchar flags= cf->invisible;
+ if (cf->flags & VERS_UPDATE_UNVERSIONED_FLAG)
+ flags|= VERS_OPTIMIZED_UPDATE;
+ *pos++= flags;
+ }
+ 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)
+{
+ 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);
+
+ for (unsigned field_no = 0; (sql_field = it++); ++field_no)
+ {
+ if (row_field.streq(sql_field->field_name))
+ {
+ DBUG_ASSERT(field_no <= uint16(~0U));
+ return uint16(field_no);
+ }
+ }
+
+ DBUG_ASSERT(0); /* Not Reachable */
+ return 0;
+}
+
+static inline
+bool has_extra2_field_flags(List<Create_field> &create_fields)
+{
+ List_iterator<Create_field> it(create_fields);
+ while (Create_field *f= it++)
+ {
+ if (f->invisible)
+ return true;
+ if (f->flags & VERS_UPDATE_UNVERSIONED_FLAG)
+ return true;
+ }
+ return false;
+}
+
+/**
Create a frm (table definition) file
@param thd Thread handler
@@ -102,20 +164,21 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
or null LEX_CUSTRING (str==0) in case of an error.
*/
-LEX_CUSTRING build_frm_image(THD *thd, const char *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)
{
- LEX_STRING str_db_type;
+ LEX_CSTRING str_db_type;
uint reclength, key_info_length, i;
ulong key_buff_length;
- ulong filepos, data_offset;
+ size_t filepos;
+ ulong data_offset;
uint options_len;
uint gis_extra2_len= 0;
uchar fileinfo[FRM_HEADER_SIZE],forminfo[FRM_FORMINFO_SIZE];
const partition_info *part_info= IF_PARTITIONING(thd->work_part_info, 0);
- int error;
+ bool error;
uchar *frm_ptr, *pos;
LEX_CUSTRING frm= {0,0};
StringBuffer<MAX_FIELD_WIDTH> vcols;
@@ -131,15 +194,15 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
error= pack_vcols(&vcols, create_fields, create_info->check_constraint_list);
thd->variables.sql_mode= save_sql_mode;
- if (error)
+ if (unlikely(error))
DBUG_RETURN(frm);
if (vcols.length())
create_info->expression_length= vcols.length() + FRM_VCOL_NEW_BASE_SIZE;
error= pack_header(thd, forminfo, create_fields, create_info,
- data_offset, db_file);
- if (error)
+ (ulong)data_offset, db_file);
+ if (unlikely(error))
DBUG_RETURN(frm);
reclength= uint2korr(forminfo+266);
@@ -147,7 +210,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
/* Calculate extra data segment length */
str_db_type= *hton_name(create_info->db_type);
/* str_db_type */
- create_info->extra_size= (2 + str_db_type.length +
+ create_info->extra_size= (uint)(2 + str_db_type.length +
2 + create_info->connect_string.length);
/*
Partition:
@@ -158,12 +221,12 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
*/
create_info->extra_size+= 6;
if (part_info)
- create_info->extra_size+= part_info->part_info_len;
+ create_info->extra_size+= (uint)part_info->part_info_len;
for (i= 0; i < keys; i++)
{
if (key_info[i].parser_name)
- create_info->extra_size+= key_info[i].parser_name->length + 1;
+ create_info->extra_size+= (uint)key_info[i].parser_name->length + 1;
}
options_len= engine_table_options_frm_length(create_info->option_list,
@@ -175,8 +238,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *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))
+ ER_TOO_LONG_TABLE_COMMENT, table->str))
DBUG_RETURN(frm);
/*
If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes,
@@ -186,7 +248,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN)
{
forminfo[46]=255;
- create_info->extra_size+= 2 + create_info->comment.length;
+ create_info->extra_size+= 2 + (uint)create_info->comment.length;
}
else
{
@@ -210,7 +272,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
prepare_frm_header(thd, reclength, fileinfo, create_info, keys, key_info);
/* one byte for a type, one or three for a length */
- uint extra2_size= 1 + 1 + create_info->tabledef_version.length;
+ size_t extra2_size= 1 + 1 + create_info->tabledef_version.length;
if (options_len)
extra2_size+= 1 + (options_len > 255 ? 3 : 1) + options_len;
@@ -220,6 +282,17 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
if (gis_extra2_len)
extra2_size+= 1 + (gis_extra2_len > 255 ? 3 : 1) + gis_extra2_len;
+ if (create_info->versioned())
+ {
+ extra2_size+= 1 + 1 + 2 * sizeof(uint16);
+ }
+
+ 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;
+ }
key_buff_length= uint4korr(fileinfo+47);
@@ -240,7 +313,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
if (frm.length > FRM_MAX_SIZE ||
create_info->expression_length > UINT_MAX32)
{
- my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table);
+ my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table->str);
DBUG_RETURN(frm);
}
@@ -276,6 +349,19 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
}
#endif /*HAVE_SPATIAL*/
+ 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);
+ }
+
+ if (has_extra2_field_flags_)
+ pos= extra2_write_field_properties(pos, create_fields);
+
int4store(pos, filepos); // end of the extra2 segment
pos+= 4;
@@ -286,7 +372,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
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);
+ MYF(0), table->str);
goto err;
}
@@ -487,7 +573,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
*pos++=(uchar) NAMES_SEP_CHAR;
for (key=keyinfo ; key != end ; key++)
{
- uchar *tmp=(uchar*) strmov((char*) pos,key->name);
+ uchar *tmp=(uchar*) strmov((char*) pos,key->name.str);
*tmp++= (uchar) NAMES_SEP_CHAR;
*tmp=0;
pos=tmp;
@@ -548,7 +634,7 @@ static bool pack_expression(String *buf, Virtual_column_info *vcol,
size_t len_off= buf->length();
buf->q_append2b(0); // to be added later
buf->q_append((char)vcol->name.length);
- buf->q_append(vcol->name.str, vcol->name.length);
+ buf->q_append(&vcol->name);
size_t expr_start= buf->length();
vcol->print(buf);
size_t expr_len= buf->length() - expr_start;
@@ -625,7 +711,8 @@ static bool pack_header(THD *thd, uchar *forminfo,
while ((field=it++))
{
if (validate_comment_length(thd, &field->comment, COLUMN_COMMENT_MAXLEN,
- ER_TOO_LONG_FIELD_COMMENT, field->field_name))
+ ER_TOO_LONG_FIELD_COMMENT,
+ field->field_name.str))
DBUG_RETURN(1);
totlength+= (size_t)field->length;
@@ -634,14 +721,14 @@ static bool pack_header(THD *thd, uchar *forminfo,
We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
as auto-update field.
*/
- if (field->sql_type == MYSQL_TYPE_TIMESTAMP &&
+ if (field->real_field_type() == MYSQL_TYPE_TIMESTAMP &&
MTYP_TYPENR(field->unireg_check) != Field::NONE &&
!time_stamp_pos)
time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
length=field->pack_length;
if ((uint) field->offset+ (uint) data_offset+ length > reclength)
reclength=(uint) (field->offset+ data_offset + length);
- n_length+= (ulong) strlen(field->field_name)+1;
+ n_length+= field->field_name.length + 1;
field->interval_id=0;
field->save_interval= 0;
if (field->interval)
@@ -672,10 +759,10 @@ static bool pack_header(THD *thd, uchar *forminfo,
{
char *dst;
const char *src= field->save_interval->type_names[pos];
- uint hex_length;
+ size_t hex_length;
length= field->save_interval->type_lengths[pos];
hex_length= length * 2;
- field->interval->type_lengths[pos]= hex_length;
+ field->interval->type_lengths[pos]= (uint)hex_length;
field->interval->type_names[pos]= dst=
(char*) thd->alloc(hex_length + 1);
octet2hex(dst, src, length);
@@ -785,7 +872,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields)
}
length+= FCOMP;
- length+= strlen(field->field_name)+1;
+ length+= field->field_name.length + 1;
length+= field->comment.length;
}
length+= 2;
@@ -799,7 +886,8 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
ulong data_offset)
{
uchar *buff= *buff_arg;
- uint int_count, comment_length= 0;
+ uint int_count;
+ size_t comment_length= 0;
Create_field *field;
DBUG_ENTER("pack_fields");
@@ -816,8 +904,8 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
int2store(buff+8,field->pack_flag);
buff[10]= (uchar) field->unireg_check;
buff[12]= (uchar) field->interval_id;
- buff[13]= (uchar) field->sql_type;
- if (field->sql_type == MYSQL_TYPE_GEOMETRY)
+ buff[13]= (uchar) field->real_field_type();
+ if (field->real_field_type() == MYSQL_TYPE_GEOMETRY)
{
buff[11]= 0;
buff[14]= (uchar) field->geom_type;
@@ -846,7 +934,7 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
it.rewind();
while ((field=it++))
{
- buff= (uchar*)strmov((char*) buff, field->field_name);
+ buff= (uchar*)strmov((char*) buff, field->field_name.str);
*buff++=NAMES_SEP_CHAR;
}
*buff++= 0;
@@ -962,13 +1050,14 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
null_pos + null_count / 8,
null_count & 7,
field->pack_flag,
- field->sql_type,
+ 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->field_name,
+ field->flags);
if (!regfield)
{
error= 1;
@@ -984,16 +1073,17 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
null_count++;
}
- if (field->sql_type == MYSQL_TYPE_BIT && !f_bit_as_char(field->pack_flag))
+ if (field->real_field_type() == MYSQL_TYPE_BIT &&
+ !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->sql_type == MYSQL_TYPE_GEOMETRY))
+ (!(field->flags & BLOB_FLAG) ||
+ field->real_field_type() == MYSQL_TYPE_GEOMETRY))
{
Item *expr= field->default_value->expr;
-
- int res= !expr->fixed && // may be already fixed if ALTER TABLE
- expr->fix_fields(thd, &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))
@@ -1002,7 +1092,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
/* If not ok or warning of level 'note' */
if (res != 0 && res != 3)
{
- my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str);
error= 1;
delete regfield; //To avoid memory leak
goto err;