Commit 4958eec7 authored by unknown's avatar unknown

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)   


mysql-test/r/func_misc.result:
  Update results
mysql-test/r/sql_mode.result:
  Update results
mysql-test/t/func_misc.test:
  Added test for uuid_short()
mysql-test/t/sql_mode.test:
  Added test for sql_mode=PAD_CHAR_TO_FULL_LENGTH (#WL921)
sql/field.cc:
  Added sql_mode PAD_CHAR_TO_FULL_LENGTH
sql/item.cc:
  Initialize uuid_short()
sql/item_create.cc:
  Added creation of uuid_short()
sql/item_func.cc:
  Added uuid_short()
sql/item_func.h:
  Added uuid_short()
sql/mysql_priv.h:
  Added sql_mode PAD_CHAR_TO_FULL_LENGTH
sql/mysqld.cc:
  Added sql_mode PAD_CHAR_TO_FULL_LENGTH
parent 51e016f1
......@@ -22,6 +22,9 @@ hex(inet_aton('127.1.1'))
select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
length(uuid()) charset(uuid()) length(unhex(replace(uuid(),_utf8'-',_utf8'')))
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;
length(format('nan', 2)) > 0
1
......
......@@ -475,9 +475,24 @@ set sql_mode=16384+(65536*4);
select @@sql_mode;
@@sql_mode
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI
set sql_mode=2147483648;
ERROR 42000: Variable 'sql_mode' can't be set to the value of '2147483648'
set sql_mode=2147483648*2;
ERROR 42000: Variable 'sql_mode' can't be set to the value of '4294967296'
select @@sql_mode;
@@sql_mode
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;
......@@ -14,6 +14,10 @@ select hex(inet_aton('127.1.1'));
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
#
......
......@@ -264,7 +264,18 @@ select @@sql_mode;
set sql_mode=16384+(65536*4);
select @@sql_mode;
--error 1231
set sql_mode=2147483648; # that mode does not exist
set sql_mode=2147483648*2; # that mode does not exist
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;
......@@ -6187,9 +6187,14 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
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) */
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);
return val_ptr;
}
......
......@@ -161,6 +161,7 @@ Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const
void item_init(void)
{
item_user_lock_init();
uuid_short_init();
}
......
......@@ -2141,6 +2141,19 @@ protected:
};
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
{
public:
......@@ -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;
Item*
......@@ -4871,6 +4894,7 @@ static Native_func_registry func_array[] =
{ C_STRING_WITH_LEN("UPDATEXML"), BUILDER(Create_func_xml_update)},
{ C_STRING_WITH_LEN("UPPER"), BUILDER(Create_func_ucase)},
{ 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("WEEKDAY"), BUILDER(Create_func_weekday)},
{ C_STRING_WITH_LEN("WEEKOFYEAR"), BUILDER(Create_func_weekofyear)},
......
......@@ -5358,3 +5358,40 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
}
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 @@ public:
const char *func_name() const { return "found_rows"; }
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);
#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2)
#define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*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
use strictly more than 64 bits by adding one more define above, you should
......
......@@ -225,8 +225,10 @@ static const char *sql_mode_names[]=
"ERROR_FOR_DIVISION_BY_ZERO",
"TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
"NO_ENGINE_SUBSTITUTION",
"PAD_CHAR_TO_FULL_LENGTH",
NullS
};
static const unsigned int sql_mode_names_len[]=
{
/*REAL_AS_FLOAT*/ 13,
......@@ -259,8 +261,10 @@ static const unsigned int sql_mode_names_len[]=
/*TRADITIONAL*/ 11,
/*NO_AUTO_CREATE_USER*/ 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,"",
sql_mode_names,
(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