summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_misc.result3
-rw-r--r--mysql-test/r/sql_mode.result19
-rw-r--r--mysql-test/t/func_misc.test4
-rw-r--r--mysql-test/t/sql_mode.test13
-rw-r--r--sql/field.cc7
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_create.cc24
-rw-r--r--sql/item_func.cc37
-rw-r--r--sql/item_func.h15
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc6
11 files changed, 126 insertions, 5 deletions
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index b4c6f0f6699..7526134c476 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -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
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index c7be653ca2e..9998a51fdc8 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -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;
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index 8ff62f68e45..7437b0008e4 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -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
#
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index 8542c2b7927..7a9036c8621 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -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;
diff --git a/sql/field.cc b/sql/field.cc
index e8718c9e407..5624294d012 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -6195,9 +6195,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;
}
diff --git a/sql/item.cc b/sql/item.cc
index f339bad78e4..3f4751a4753 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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();
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 8ff78ef1b48..8c97b596336 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -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)},
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 732c4403ca2..ab57b047201 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -5399,3 +5399,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;
+}
diff --git a/sql/item_func.h b/sql/item_func.h
index 6457013b160..21dce696d61 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1551,3 +1551,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;}
+};
+
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 93f290b12e7..ffe180fd474 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -399,6 +399,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
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d6efebd32c4..796dc72a98d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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 };