Added sql_mode PAD_CHAR_TO_FULL_LENGTH (WL#921)

This pads the value of CHAR columns with spaces up to full column length (according to ANSI)
It's not makde part of oracle or ansi mode yet, as this would cause a notable behaviour change.
Added uuid_short(), a generator for increasing 'unique' longlong integers (8 bytes)   
parent fc610365
...@@ -22,6 +22,9 @@ hex(inet_aton('127.1.1')) ...@@ -22,6 +22,9 @@ hex(inet_aton('127.1.1'))
select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8''))); select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
length(uuid()) charset(uuid()) length(unhex(replace(uuid(),_utf8'-',_utf8''))) length(uuid()) charset(uuid()) length(unhex(replace(uuid(),_utf8'-',_utf8'')))
36 utf8 16 36 utf8 16
select cast(uuid_short()-uuid_short() as signed);
cast(uuid_short()-uuid_short() as signed)
-1
select length(format('nan', 2)) > 0; select length(format('nan', 2)) > 0;
length(format('nan', 2)) > 0 length(format('nan', 2)) > 0
1 1
......
...@@ -475,9 +475,24 @@ set sql_mode=16384+(65536*4); ...@@ -475,9 +475,24 @@ set sql_mode=16384+(65536*4);
select @@sql_mode; select @@sql_mode;
@@sql_mode @@sql_mode
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI
set sql_mode=2147483648; set sql_mode=2147483648*2;
ERROR 42000: Variable 'sql_mode' can't be set to the value of '2147483648' ERROR 42000: Variable 'sql_mode' can't be set to the value of '4294967296'
select @@sql_mode; select @@sql_mode;
@@sql_mode @@sql_mode
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI
set sql_mode=PAD_CHAR_TO_FULL_LENGTH;
create table t1 (a int auto_increment primary key, b char(5));
insert into t1 (b) values('a'),('b\t'),('c ');
select concat('x',b,'x') from t1;
concat('x',b,'x')
xa x
xb x
xc x
set sql_mode=0;
select concat('x',b,'x') from t1;
concat('x',b,'x')
xax
xb x
xcx
drop table t1;
SET @@SQL_MODE=@OLD_SQL_MODE; SET @@SQL_MODE=@OLD_SQL_MODE;
...@@ -14,6 +14,10 @@ select hex(inet_aton('127.1.1')); ...@@ -14,6 +14,10 @@ select hex(inet_aton('127.1.1'));
select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8''))); select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
# As we can assume we are the only user for the mysqld server, the difference
# between two calls should be -1
select cast(uuid_short()-uuid_short() as signed);
# #
# Test for core dump with nan # Test for core dump with nan
# #
......
...@@ -264,7 +264,18 @@ select @@sql_mode; ...@@ -264,7 +264,18 @@ select @@sql_mode;
set sql_mode=16384+(65536*4); set sql_mode=16384+(65536*4);
select @@sql_mode; select @@sql_mode;
--error 1231 --error 1231
set sql_mode=2147483648; # that mode does not exist set sql_mode=2147483648*2; # that mode does not exist
select @@sql_mode; select @@sql_mode;
#
# Test WL921: Retain spaces when retrieving CHAR column values
set sql_mode=PAD_CHAR_TO_FULL_LENGTH;
create table t1 (a int auto_increment primary key, b char(5));
insert into t1 (b) values('a'),('b\t'),('c ');
select concat('x',b,'x') from t1;
set sql_mode=0;
select concat('x',b,'x') from t1;
drop table t1;
SET @@SQL_MODE=@OLD_SQL_MODE; SET @@SQL_MODE=@OLD_SQL_MODE;
...@@ -6187,9 +6187,14 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), ...@@ -6187,9 +6187,14 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr) String *val_ptr)
{ {
ASSERT_COLUMN_MARKED_FOR_READ; ASSERT_COLUMN_MARKED_FOR_READ;
uint length= field_charset->cset->lengthsp(field_charset, ptr, field_length);
/* See the comment for Field_long::store(long long) */ /* See the comment for Field_long::store(long long) */
DBUG_ASSERT(table->in_use == current_thd); DBUG_ASSERT(table->in_use == current_thd);
uint length;
if (table->in_use->variables.sql_mode &
MODE_PAD_CHAR_TO_FULL_LENGTH)
length= my_charpos(field_charset, ptr, ptr + field_length, field_length);
else
length= field_charset->cset->lengthsp(field_charset, ptr, field_length);
val_ptr->set((const char*) ptr, length, field_charset); val_ptr->set((const char*) ptr, length, field_charset);
return val_ptr; return val_ptr;
} }
......
...@@ -161,6 +161,7 @@ Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const ...@@ -161,6 +161,7 @@ Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const
void item_init(void) void item_init(void)
{ {
item_user_lock_init(); item_user_lock_init();
uuid_short_init();
} }
......
...@@ -2141,6 +2141,19 @@ class Create_func_uuid : public Create_func_arg0 ...@@ -2141,6 +2141,19 @@ class Create_func_uuid : public Create_func_arg0
}; };
class Create_func_uuid_short : public Create_func_arg0
{
public:
virtual Item *create(THD *thd);
static Create_func_uuid_short s_singleton;
protected:
Create_func_uuid_short() {}
virtual ~Create_func_uuid_short() {}
};
class Create_func_version : public Create_func_arg0 class Create_func_version : public Create_func_arg0
{ {
public: public:
...@@ -4532,6 +4545,16 @@ Create_func_uuid::create(THD *thd) ...@@ -4532,6 +4545,16 @@ Create_func_uuid::create(THD *thd)
} }
Create_func_uuid_short Create_func_uuid_short::s_singleton;
Item*
Create_func_uuid_short::create(THD *thd)
{
thd->lex->binlog_row_based_if_mixed= TRUE;
return new (thd->mem_root) Item_func_uuid_short();
}
Create_func_version Create_func_version::s_singleton; Create_func_version Create_func_version::s_singleton;
Item* Item*
...@@ -4871,6 +4894,7 @@ static Native_func_registry func_array[] = ...@@ -4871,6 +4894,7 @@ static Native_func_registry func_array[] =
{ C_STRING_WITH_LEN("UPDATEXML"), BUILDER(Create_func_xml_update)}, { C_STRING_WITH_LEN("UPDATEXML"), BUILDER(Create_func_xml_update)},
{ C_STRING_WITH_LEN("UPPER"), BUILDER(Create_func_ucase)}, { C_STRING_WITH_LEN("UPPER"), BUILDER(Create_func_ucase)},
{ C_STRING_WITH_LEN("UUID"), BUILDER(Create_func_uuid)}, { C_STRING_WITH_LEN("UUID"), BUILDER(Create_func_uuid)},
{ C_STRING_WITH_LEN("UUID_SHORT"), BUILDER(Create_func_uuid_short)},
{ C_STRING_WITH_LEN("VERSION"), BUILDER(Create_func_version)}, { C_STRING_WITH_LEN("VERSION"), BUILDER(Create_func_version)},
{ C_STRING_WITH_LEN("WEEKDAY"), BUILDER(Create_func_weekday)}, { C_STRING_WITH_LEN("WEEKDAY"), BUILDER(Create_func_weekday)},
{ C_STRING_WITH_LEN("WEEKOFYEAR"), BUILDER(Create_func_weekofyear)}, { C_STRING_WITH_LEN("WEEKOFYEAR"), BUILDER(Create_func_weekofyear)},
......
...@@ -5358,3 +5358,40 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) ...@@ -5358,3 +5358,40 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
} }
DBUG_RETURN(res); DBUG_RETURN(res);
} }
/*
uuid_short handling.
The short uuid is defined as a longlong that contains the following bytes:
Bytes Comment
1 Server_id & 255
4 Startup time of server in seconds
3 Incrementor
This means that an uuid is guaranteed to be unique
even in a replication environment if the following holds:
- The last byte of the server id is unique
- If you between two shutdown of the server don't get more than
an average of 2^24 = 16M calls to uuid_short() per second.
*/
ulonglong uuid_value;
void uuid_short_init()
{
uuid_value= (((ulonglong) server_id << 56) +
(ulonglong) server_start_time << 24);
}
longlong Item_func_uuid_short::val_int()
{
ulonglong val;
pthread_mutex_lock(&LOCK_uuid_generator);
val= uuid_value++;
pthread_mutex_unlock(&LOCK_uuid_generator);
return (longlong) val;
}
...@@ -1528,3 +1528,18 @@ class Item_func_found_rows :public Item_int_func ...@@ -1528,3 +1528,18 @@ class Item_func_found_rows :public Item_int_func
const char *func_name() const { return "found_rows"; } const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; } void fix_length_and_dec() { decimals= 0; maybe_null=0; }
}; };
void uuid_short_init();
class Item_func_uuid_short :public Item_int_func
{
public:
Item_func_uuid_short() :Item_int_func() {}
const char *func_name() const { return "uuid_short"; }
longlong val_int();
void fix_length_and_dec()
{ max_length= 21; unsigned_flag=1; }
bool check_partition_func_processor(byte *int_arg) {return FALSE;}
};
...@@ -401,6 +401,8 @@ MY_LOCALE *my_locale_by_number(uint number); ...@@ -401,6 +401,8 @@ MY_LOCALE *my_locale_by_number(uint number);
#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2) #define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2)
#define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2) #define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2)
#define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2) #define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2)
#define MODE_PAD_CHAR_TO_FULL_LENGTH (MODE_NO_ENGINE_SUBSTITUTION*2)
/* /*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
use strictly more than 64 bits by adding one more define above, you should use strictly more than 64 bits by adding one more define above, you should
......
...@@ -225,8 +225,10 @@ static const char *sql_mode_names[]= ...@@ -225,8 +225,10 @@ static const char *sql_mode_names[]=
"ERROR_FOR_DIVISION_BY_ZERO", "ERROR_FOR_DIVISION_BY_ZERO",
"TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
"NO_ENGINE_SUBSTITUTION", "NO_ENGINE_SUBSTITUTION",
"PAD_CHAR_TO_FULL_LENGTH",
NullS NullS
}; };
static const unsigned int sql_mode_names_len[]= static const unsigned int sql_mode_names_len[]=
{ {
/*REAL_AS_FLOAT*/ 13, /*REAL_AS_FLOAT*/ 13,
...@@ -259,8 +261,10 @@ static const unsigned int sql_mode_names_len[]= ...@@ -259,8 +261,10 @@ static const unsigned int sql_mode_names_len[]=
/*TRADITIONAL*/ 11, /*TRADITIONAL*/ 11,
/*NO_AUTO_CREATE_USER*/ 19, /*NO_AUTO_CREATE_USER*/ 19,
/*HIGH_NOT_PRECEDENCE*/ 19, /*HIGH_NOT_PRECEDENCE*/ 19,
/*NO_ENGINE_SUBSTITUTION*/ 22 /*NO_ENGINE_SUBSTITUTION*/ 22,
/*PAD_CHAR_TO_FULL_LENGTH*/ 23
}; };
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
sql_mode_names, sql_mode_names,
(unsigned int *)sql_mode_names_len }; (unsigned int *)sql_mode_names_len };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment