Hello Jerome, On 01/24/2017 07:33 PM, jerome brauge wrote: > Hello Alexander, > This patch works fine. Thanks.
Thanks for confirmation. The patch is now in review. I'll push it as soon as it gets reviewed, then will let you know. > But I have a question: why do you want to preserve behavior of concat ? > If it's for compatibility reason with older version, how do you think manage > the required changes in some functions? > For example, select substr('ab',0,1) return an empty string on Mariadb but > 'a' on Oracle. > > Perhaps, in this case an new sql_mode can preserve older semantic. We haven't thought about it yet. > > Best regards. > Jérôme. > > -----Message d'origine----- > De : Alexander Barkov [mailto:b...@mariadb.org] > Envoyé : mardi 24 janvier 2017 08:05 > À : jerome brauge > Cc : MariaDB Developers; Sergei Golubchik > Objet : Re: MDEV-10142 - bb-10.2-compatibility > > Hi Jerome, > > > On 01/23/2017 06:39 PM, jerome brauge wrote: >> Hi Alexander, >> I think something is wrong in Item_func_concat_operator_oracle, if the first >> argument is empty and the second argument is null ,then res is null and >> res->set_charset fail. >> Example: select ''||null||'a' > > Right, thanks for noticing this. > >> >> >> for (i++ ; i < arg_count ; i++) >> { >> if (res->length() == 0) >> { >> // See comments in Item_func_concat::val_str() >> -->> if (!(res= arg_val_str(i, str, &is_const))) > > "res" should only be assigned if arg_val_str() returns a non-null value. > Fixed the problem and extended the tests to cover this combination, and many > other combinations. > > The new version is attached. > > Thanks for cooperation! > > >> continue; >> } >> else >> { >> const String *res2; >> if (!(res2= args[i]->val_str(use_as_buff))) >> continue; >> if (!(res= append_value(res, is_const, str, &use_as_buff, res2))) >> goto null; >> is_const= 0; >> } >> } >> -->> res->set_charset(collation.collation); >> >> Best regards, >> Jérôme. >> >> >> -----Message d'origine----- >> De : Alexander Barkov [mailto:b...@mariadb.org] Envoyé : lundi 23 >> janvier 2017 12:28 À : jerome brauge Cc : MariaDB Developers; Sergei >> Golubchik Objet : Re: MDEV-10142 - bb-10.2-compatibility >> >> Hi Jerome, >> >> >> On 01/19/2017 05:15 PM, jerome brauge wrote: >>> Hello Alexander, Sergei, >>> Concat function exists in Oracle, but it accepts only two operand. Due to >>> this, it's not very useful and we don't use it. >> >> Thanks for clarification! >> >>> Changing only operator || is fine for us. >> >> I created an MDEV for this: >> https://jira.mariadb.org/browse/MDEV-11880 >> >> and modified your patch to implement this approach. >> >> To safe on performance slightly, I created two different classes for the >> MariaDB style concatenation and for Oracle style || concatenation. >> >> Please find the new version attached. Do you think it's fine? >> >> >> Note, before we can push it, we'd like to fix this problem first: >> >> https://jira.mariadb.org/browse/MDEV-11848 >> >> Greetings. >> >>> >>> Regards, >>> Jérôme. >>> >>> -----Message d'origine----- >>> De : Alexander Barkov [mailto:b...@mariadb.org] Envoyé : jeudi 19 >>> janvier 2017 13:18 À : jerome brauge Cc : MariaDB Developers; Sergei >>> Golubchik Objet : Re: MDEV-10142 - bb-10.2-compatibility >>> >>> Hello Jerome, >>> >>> >>> On 01/16/2017 02:45 PM, jerome brauge wrote: >>>> Hello Alexander, >>>> According to your comments, this is the new version. >>> >>> Thanks for addressing my suggestions. >>> >>> We're discussing the change with our architect Sergei Golubchik. >>> >>> Briefly, the idea is: >>> >>> Perhaps we should not change the function CONCAT(). >>> This is a non-standard MySQL/MariaDB function, and it does not exist in >>> Oracle. So probably it should stay sql_mode independent, while sql_mode >>> should affect only the concatenation operator ||. >>> >>> Would this solution work for you? >>> >>> We're still discussing details. I'll get back to you soon. >>> >>> Greetings. >>> >>>> >>>> Best regards, >>>> Jérôme. >>>> >>>> >>>> -----Message d'origine----- >>>> De : Alexander Barkov [mailto:b...@mariadb.org] Envoyé : vendredi 30 >>>> décembre 2016 10:36 À : jerome brauge Cc : MariaDB Developers Objet : >>>> Re: MDEV-10142 - bb-10.2-compatibility >>>> >>>> Hello Jerome, >>>> >>>> >>>> On 12/29/2016 08:15 PM, jerome brauge wrote: >>>>> Hello Alexander, >>>>> I built a patch for concat of strings and nulls when sql_mode=oracle. >>>>> Can you review it ? >>>> >>>> Thank you very much for your patch. >>>> It generally looks fine. >>>> I suggest only small changes. >>>> >>>> Please see inline. >>>> >>>>> >>>>> Best regards, >>>>> Jérôme. >>>>> >>>>> >>>> >>>> >>>>> From 6250ce0bcfe563491b25d2e1b4c879f697623537 Mon Sep 17 00:00:00 >>>>> 2001 >>>>> From: jb <jb@JB-PC> >>>>> Date: Mon, 26 Dec 2016 15:03:41 +0100 >>>>> Subject: [PATCH] Adding sql_mode=CONCAT_NULL_YIELDS_NULL_OFF which >>>>> is added by >>>> >>>> I'm not sure about _OFF at the end. It sounds confusing. >>>> >>>> >>>> Perhaps CONCAT_NULL_YIELDS_NOT_NULL would be a better name. >>>> >>>> >>>>> default to sql_mode=ORACLE. Concatenating a zero-length character >>>>> string with another operand always results in the other operand, >>>>> so null can result only from the concatenation of two null strings. >>>>> >>>>> --- >>>>> include/my_bit.h | 5 +++ >>>>> .../suite/compat/oracle/r/func_concat.result | 16 ++++++++ >>>>> mysql-test/suite/compat/oracle/t/func_concat.test | 17 ++++++++ >>>>> scripts/mysql_system_tables.sql | 4 +- >>>>> scripts/mysql_system_tables_fix.sql | 3 +- >>>>> sql/event_db_repository.cc | 2 +- >>>>> sql/item_strfunc.cc | 47 >>>>> +++++++++++++++++----- >>>>> sql/sp.cc | 2 +- >>>>> sql/sql_class.h | 1 + >>>>> sql/sys_vars.cc | 5 ++- >>>>> sql/sys_vars.ic | 8 ++-- >>>>> 11 files changed, 89 insertions(+), 21 deletions(-) create mode >>>>> 100644 mysql-test/suite/compat/oracle/r/func_concat.result >>>>> create mode 100644 >>>>> mysql-test/suite/compat/oracle/t/func_concat.test >>>>> >>>>> diff --git a/include/my_bit.h b/include/my_bit.h index >>>>> a50403c..4918815 100644 >>>>> --- a/include/my_bit.h >>>>> +++ b/include/my_bit.h >>>>> @@ -130,6 +130,11 @@ static inline uint32 my_set_bits(int n) >>>>> return (((1UL << (n - 1)) - 1) << 1) | 1; } >>>>> >>>>> +static inline uint64 my_set_bits64(int n) { >>>>> + return (((1ULL << (n - 1)) - 1) << 1) | 1; } >>>>> + >>>>> C_MODE_END >>>>> >>>>> #endif /* MY_BIT_INCLUDED */ >>>>> diff --git a/mysql-test/suite/compat/oracle/r/func_concat.result >>>>> b/mysql-test/suite/compat/oracle/r/func_concat.result >>>>> new file mode 100644 >>>>> index 0000000..d055192 >>>>> --- /dev/null >>>>> +++ b/mysql-test/suite/compat/oracle/r/func_concat.result >>>>> @@ -0,0 +1,16 @@ >>>>> +SET sql_mode=ORACLE; >>>>> +SELECT 'a'||'b'; >>>>> +'a'||'b' >>>>> +ab >>>>> +SELECT 'a'||'b'||NULL; >>>>> +'a'||'b'||NULL >>>>> +ab >>>>> +SELECT NULL||'b'||NULL; >>>>> +NULL||'b'||NULL >>>>> +b >>>>> +SELECT NULL||NULL||'c'; >>>>> +NULL||NULL||'c' >>>>> +c >>>>> +SELECT NULL||NULL; >>>>> +NULL||NULL >>>>> +NULL >>>> >>>> >>>> Can you please add tests with table fields? >>>> The implementation of Item_func_concat:val_str() use >>>> args[x]->const_item(). So using non-const arguments would improve coverage. >>>> >>>> Something like this would be nice: >>>> >>>> CREATE TABLE t1 (a VARCHAR(10), b VARCHAR(10), c VARCHAR(10)); >>>> INSERT INTO t1 VALUES (NULL,NULL,NULL); INSERT INTO t1 VALUES >>>> ('a',NULL,NULL); INSERT INTO t1 VALUES (NULL,'b',NULL); INSERT INTO >>>> t1 VALUES (NULL,NULL,'c'); INSERT INTO t1 VALUES ('a','b',NULL); >>>> INSERT INTO t1 VALUES (NULL,'b','c'); INSERT INTO t1 VALUES >>>> ('a',NULL,'c'); SELECT a||b||c FROM t1; DROP TABLE t1; >>>> >>>> >>>> >>>>> diff --git a/mysql-test/suite/compat/oracle/t/func_concat.test >>>>> b/mysql-test/suite/compat/oracle/t/func_concat.test >>>>> new file mode 100644 >>>>> index 0000000..8d84707 >>>>> --- /dev/null >>>>> +++ b/mysql-test/suite/compat/oracle/t/func_concat.test >>>>> @@ -0,0 +1,17 @@ >>>>> +# >>>>> +# Testing CONCAT with null value >>>>> +# >>>>> + >>>>> +SET sql_mode=ORACLE; >>>>> + >>>>> +SELECT 'a'||'b'; >>>>> + >>>>> +SELECT 'a'||'b'||NULL; >>>>> + >>>>> +SELECT NULL||'b'||NULL; >>>>> + >>>>> +SELECT NULL||NULL||'c'; >>>>> + >>>>> +SELECT NULL||NULL; >>>>> + >>>>> + >>>>> diff --git a/scripts/mysql_system_tables.sql >>>>> b/scripts/mysql_system_tables.sql index 7b61416..eb2c97f 100644 >>>>> --- a/scripts/mysql_system_tables.sql >>>>> +++ b/scripts/mysql_system_tables.sql >>>>> @@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( >>>>> Time_zone_id int unsign >>>>> >>>>> CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time >>>>> bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY >>>>> TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 >>>>> comment='Leap seconds information for time zones'; >>>>> >>>>> -CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin >>>>> DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type >>>>> enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) >>>>> DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, >>>>> sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', >>>>> 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, >>>>> is_deterministic >>>>> enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type >>>>> enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list >>>>> blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, >>>>> definer >>>>> char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp >>>>> NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, >>>>> modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode >>>>> set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', >>>>> 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', >>>>> 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', >>>>> 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', >>>>> 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', >>>>> 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', >>>>> 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', >>>>> 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', >>>>> 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', >>>>> 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT >>>>> NULL, comment text collate utf8_bin NOT NULL, character_set_client >>>>> char(32) collate utf8_bin, collation_connection char(32) collate >>>>> utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 >>>>> longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set >>>>> utf8 comment='Stored Procedures'; >>>>> +CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin >>>>> +DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type >>>>> +enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) >>>>> +DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, >>>>> +sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', >>>>> +'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, >>>>> +is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, >>>>> +security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT >>>>> +NULL, param_list blob NOT NULL, returns longblob NOT NULL, body >>>>> +longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' >>>>> +NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON >>>>> +UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT >>>>> +'0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', >>>>> +'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', >>>>> +'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', >>>>> +'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', >>>>> +'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', >>>>> +'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', >>>>> +'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', >>>>> +'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', >>>>> +'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', >>>>> +'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', >>>>> +'NO_ENGINE_SUBSTITUTION', >>>>> +'PAD_CHAR_TO_FULL_LENGTH','CONCAT_NULL_YIELDS_NULL_OFF') DEFAULT '' >>>>> +NOT NULL, comment text collate utf8_bin NOT NULL, >>>>> +character_set_client char(32) collate utf8_bin, >>>>> +collation_connection >>>>> +char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, >>>>> +body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM >>>>> +character set utf8 comment='Stored Procedures'; >>>>> >>>>> CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' >>>>> NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary >>>>> DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci >>>>> DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, >>>>> Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter >>>>> Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp >>>>> timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, >>>>> PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor >>>>> (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin >>>>> comment='Procedure privileges'; >>>>> >>>>> @@ -101,7 +101,7 @@ PREPARE stmt FROM @str; EXECUTE stmt; DROP >>>>> PREPARE stmt; >>>>> >>>>> -CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 >>>>> COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET >>>>> utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) >>>>> CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at >>>>> DATETIME default NULL, interval_value int(11) default NULL, >>>>> interval_field >>>>> ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND',' >>>>> M >>>>> ICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR >>>>> _ >>>>> M >>>>> I >>>>> NUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSE >>>>> C >>>>> O >>>>> N >>>>> D','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created >>>>> TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE >>>>> CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 >>>>> 00:00:00', last_executed DATETIME default NULL, starts DATETIME >>>>> default NULL, ends DATETIME default NULL, status >>>>> ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default >>>>> 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default >>>>> 'DROP', sql_mode >>>>> set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE',' >>>>> I >>>>> G >>>>> NORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION' >>>>> ,'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO >>>>> _ >>>>> K >>>>> E >>>>> Y_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40' >>>>> , >>>>> 'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS >>>>> _ >>>>> T >>>>> A >>>>> BLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID >>>>> _ >>>>> D >>>>> A >>>>> TES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER' >>>>> , >>>>> 'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LE >>>>> N >>>>> G >>>>> T >>>>> H') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 >>>>> COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED >>>>> NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT >>>>> 'SYSTEM', character_set_client char(32) collate utf8_bin, >>>>> collation_connection >>>>> char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, >>>>> body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT >>>>> CHARSET=utf8 COMMENT 'Events'; >>>>> +CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 >>>>> +COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET >>>>> +utf8 NOT NULL default '', body longblob NOT NULL, definer >>>>> +char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', >>>>> +execute_at DATETIME default NULL, interval_value int(11) default >>>>> +NULL, interval_field >>>>> +ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND',' >>>>> +MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HO >>>>> +U >>>>> +R >>>>> +_ >>>>> +MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICR >>>>> +O >>>>> +S >>>>> +E >>>>> +COND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, >>>>> +created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE >>>>> +CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 >>>>> +00:00:00', last_executed DATETIME default NULL, starts DATETIME >>>>> +default NULL, ends DATETIME default NULL, status >>>>> +ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default >>>>> +'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default >>>>> +'DROP', sql_mode >>>>> +set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE',' >>>>> +I >>>>> +GNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRAC >>>>> +T >>>>> +I >>>>> +O >>>>> +N','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',' >>>>> +N >>>>> +O >>>>> +_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MY >>>>> +S >>>>> +Q >>>>> +L >>>>> +40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_ >>>>> +T >>>>> +R >>>>> +A >>>>> +NS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','I >>>>> +N >>>>> +V >>>>> +A >>>>> +LID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CRE >>>>> +A >>>>> +T >>>>> +E >>>>> +_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO >>>>> +_ >>>>> +F >>>>> +U >>>>> +LL_LENGTH','CONCAT_NULL_YIELDS_NULL_OFF') DEFAULT '' NOT NULL, >>>>> +comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL >>>>> +default '', originator INTEGER UNSIGNED NOT NULL, time_zone >>>>> +char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', >>>>> +character_set_client >>>>> +char(32) collate utf8_bin, collation_connection char(32) collate >>>>> +utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 >>>>> +longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT >>>>> +CHARSET=utf8 COMMENT 'Events'; >>>>> >>>>> SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS >>>>> innodb_table_stats ( >>>>> database_name VARCHAR(64) NOT NULL, >>>>> diff --git a/scripts/mysql_system_tables_fix.sql >>>>> b/scripts/mysql_system_tables_fix.sql >>>>> index ea1059c..b3c0ce9 100644 >>>>> --- a/scripts/mysql_system_tables_fix.sql >>>>> +++ b/scripts/mysql_system_tables_fix.sql >>>>> @@ -442,7 +442,8 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT >>>>> NULL, >>>>> 'NO_AUTO_CREATE_USER', >>>>> 'HIGH_NOT_PRECEDENCE', >>>>> 'NO_ENGINE_SUBSTITUTION', >>>>> - 'PAD_CHAR_TO_FULL_LENGTH' >>>>> + 'PAD_CHAR_TO_FULL_LENGTH', >>>>> + 'CONCAT_NULL_YIELDS_NULL_OFF' >>>>> ) DEFAULT '' NOT NULL, >>>>> DEFAULT CHARACTER SET utf8; >>>>> >>>>> diff --git a/sql/event_db_repository.cc >>>>> b/sql/event_db_repository.cc index 9de55c4..c279a85 100644 >>>>> --- a/sql/event_db_repository.cc >>>>> +++ b/sql/event_db_repository.cc >>>>> @@ -123,7 +123,7 @@ const TABLE_FIELD_TYPE >>>>> event_table_fields[ET_FIELD_COUNT] = >>>>> >>>>> "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES'," >>>>> >>>>> "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," >>>>> "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," >>>>> - >>>>> "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") >>>>> }, >>>>> + >>>>> + "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL >>>>> + _ >>>>> + L >>>>> + E >>>>> + NGTH','CONCAT_NULL_YIELDS_NULL_OFF')") }, >>>>> {NULL, 0} >>>>> }, >>>>> { >>>>> diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index >>>>> fe1c470..7b22f4b 100644 >>>>> --- a/sql/item_strfunc.cc >>>>> +++ b/sql/item_strfunc.cc >>>>> @@ -619,19 +619,42 @@ String *Item_func_concat::val_str(String *str) >>>>> DBUG_ASSERT(fixed == 1); >>>>> String *res,*res2,*use_as_buff; >>>>> uint i; >>>>> - bool is_const= 0; >>>>> + bool is_const = 0; >>>> >>>> Please follow the MariaDB coding style: >>>> >>>> 1. In assignment operator: >>>> - there is no space before "=" >>>> - there is one space after "=". >>>> >>>> So the above line "bool is_const= 0;" should not be modified. >>>> >>>> 2. Don't use tabs, use spaces instead. >>>> >>>> 3. There should not be trailing white spaces. >>>> Please use "git diff --check". >>>> >>>> >>>> Note, the old code may not always be following the coding style. >>>> So don't be confused :) Some lines are old enough, older than the coding >>>> style policy. >>>> >>>> Please make sure that all new and modified line follows the coding style. >>>> >>>> >>>>> + uint firstarg = 0; >>>>> + uint nextarg = 1; >>>> >>>> These two variables basically repeat each other, and repeat "i". >>>> >>>> Also, I noticed that args[0]->val_str() is called twice. >>>> >>>> One time in the "// Search first non null argument" loop, and then before >>>> the "for (i= nextarg; i < arg_count ; i++)" again. >>>> >>>> I suggest to remove firstarg and nextarg and always use "i" instead, and >>>> to make sure that val_str() is not called twice for the same argument. >>>> >>>> >>>> >>>>> >>>>> - null_value=0; >>>>> - if (!(res=args[0]->val_str(str))) >>>>> + if (current_thd->variables.sql_mode & >>>>> + MODE_CONCAT_NULL_YIELDS_NULL_OFF) >>>> >>>> current_thd is a heavy function. >>>> It's better to avoid its execution per row. >>>> Please add a new boolean member and initialize it to false in constructors: >>>> >>>> >>>> class Item_func_concat :public Item_str_func { >>>> m_null_yierds_not_null; >>>> String tmp_value; >>>> public: >>>> Item_func_concat(THD *thd, List<Item> &list): >>>> Item_str_func(thd, list), >>>> m_null_yield_not_null(false) >>>> {} >>>> Item_func_concat(THD *thd, Item *a, Item *b): >>>> Item_str_func(thd, a, b), >>>> m_null_yield_not_null(false) >>>> {} >>>> ... >>>> }; >>>> >>>> >>>> and then set it according to sql_mode in fix_length_and_dec(): >>>> >>>> >>>> >>>> void Item_func_concat::fix_length_and_dec() >>>> { >>>> m_null_yields_not_null= current_thd->variables.sql_mode & >>>> MODE_CONCAT_NULL_YIELDS_NULL_OFF; >>>> ... >>>> } >>>> >>>> >>>> After this, we change all tests like: >>>> >>>> if (current_thd->variables.sql_mode & >>>> MODE_CONCAT_NULL_YIELDS_NULL_OFF) >>>> >>>> to >>>> >>>> if (m_null_yields_not_null) >>>> >>>> >>>>> + { >>>>> + // Search first non null argument >>>>> + i = 0; >>>>> + while (!(res = args[i]->val_str(str))) >>>>> + { >>>>> + if (++i == arg_count) >>>>> + break; >>>>> + } >>>>> + if (res) >>>>> + { >>>>> + firstarg=i++; >>>>> + nextarg = i; >>>>> + } >>>>> + } >>>> >>>> I find something like this more readable: >>>> >>>> ... >>>> // Search first non null argument >>>> for (i= 0; i < arg_count; i++) >>>> { >>>> if ((res= args[i]->val_str(str)) >>>> break; >>>> } >>>> if (i == arg_count) >>>> goto null; >>>> ... >>>> >>>> >>>>> + >>>>> + null_value = 0; >>>>> + if (!(res = args[firstarg]->val_str(str))) >>>> >>>> There are tabs in the above two lines. Please use spaces. >>>> >>>> >>>>> goto null; >>>>> - use_as_buff= &tmp_value; >>>>> - is_const= args[0]->const_item(); >>>>> - for (i=1 ; i < arg_count ; i++) >>>>> + use_as_buff = &tmp_value; >>>>> + is_const = args[firstarg]->const_item(); >>>>> + >>>>> + for (i= nextarg; i < arg_count ; i++) >>>>> { >>>>> if (res->length() == 0) >>>>> { >>>>> - if (!(res=args[i]->val_str(str))) >>>>> - goto null; >>>>> + if (!(res = args[i]->val_str(str))) >>>>> + { >>>>> + if (current_thd->variables.sql_mode & >>>>> + MODE_CONCAT_NULL_YIELDS_NULL_OFF) >>>> >>>> if (m_null_yields_not_null) >>>> >>>>> + continue; >>>>> + goto null; >>>>> + } >>>>> /* >>>>> CONCAT accumulates its result in the result of its the first >>>>> non-empty argument. Because of this we need is_const to be >>>>> @@ >>>>> -641,8 +664,12 @@ String *Item_func_concat::val_str(String *str) >>>>> } >>>>> else >>>>> { >>>>> - if (!(res2=args[i]->val_str(use_as_buff))) >>>>> - goto null; >>>>> + if (!(res2 = args[i]->val_str(use_as_buff))) >>>>> + { >>>>> + if (current_thd->variables.sql_mode & >>>>> + MODE_CONCAT_NULL_YIELDS_NULL_OFF) >>>> >>>> if (m_null_yields_not_null) >>>> >>>> >>>>> + continue; >>>>> + goto null; >>>>> + } >>>>> if (res2->length() == 0) >>>>> continue; >>>>> if (res->length()+res2->length() > diff --git a/sql/sp.cc >>>>> b/sql/sp.cc index eb542a6..288b7a9 100644 >>>>> --- a/sql/sp.cc >>>>> +++ b/sql/sp.cc >>>>> @@ -130,7 +130,7 @@ TABLE_FIELD_TYPE >>>>> proc_table_fields[MYSQL_PROC_FIELD_COUNT] = >>>>> >>>>> "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES'," >>>>> >>>>> "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," >>>>> "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," >>>>> - >>>>> "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") >>>>> }, >>>>> + >>>>> + "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL >>>>> + _ >>>>> + L >>>>> + E >>>>> + NGTH','CONCAT_NULL_YIELDS_NULL_OFF')") }, >>>>> { NULL, 0 } >>>>> }, >>>>> { >>>>> diff --git a/sql/sql_class.h b/sql/sql_class.h index >>>>> 6f8e884..c754092 >>>>> 100644 >>>>> --- a/sql/sql_class.h >>>>> +++ b/sql/sql_class.h >>>>> @@ -139,6 +139,7 @@ enum enum_binlog_row_image { >>>>> #define MODE_HIGH_NOT_PRECEDENCE (1ULL << 29) >>>>> #define MODE_NO_ENGINE_SUBSTITUTION (1ULL << 30) >>>>> #define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) >>>>> +#define MODE_CONCAT_NULL_YIELDS_NULL_OFF (1ULL << 32) >>>>> >>>>> /* Bits for different old style modes */ >>>>> #define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) >>>>> diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index >>>>> 27e6463..c51b1de3 >>>>> 100644 >>>>> --- a/sql/sys_vars.cc >>>>> +++ b/sql/sys_vars.cc >>>>> @@ -3032,7 +3032,8 @@ export sql_mode_t expand_sql_mode(sql_mode_t >>>>> sql_mode) >>>>> sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | >>>>> MODE_IGNORE_SPACE | >>>>> MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | >>>>> - MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); >>>>> + MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER | >>>>> + MODE_CONCAT_NULL_YIELDS_NULL_OFF); >>>>> if (sql_mode & MODE_MSSQL) >>>>> sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | >>>>> MODE_IGNORE_SPACE | @@ -3097,7 +3098,7 @@ static >>>>> const char *sql_mode_names[]= >>>>> "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", >>>>> "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL", >>>>> "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", >>>>> "NO_ENGINE_SUBSTITUTION", >>>>> - "PAD_CHAR_TO_FULL_LENGTH", >>>>> + "PAD_CHAR_TO_FULL_LENGTH","CONCAT_NULL_YIELDS_NULL_OFF", >>>>> 0 >>>>> }; >>>>> >>>>> diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index >>>>> c7f148a..fc93534 >>>>> 100644 >>>>> --- a/sql/sys_vars.ic >>>>> +++ b/sql/sys_vars.ic >>>>> @@ -1228,7 +1228,7 @@ class Sys_var_flagset: public Sys_var_typelib >>>>> global_var(ulonglong)= def_val; >>>>> SYSVAR_ASSERT(typelib.count > 1); >>>>> SYSVAR_ASSERT(typelib.count <= 65); >>>>> - SYSVAR_ASSERT(def_val < my_set_bits(typelib.count)); >>>>> + SYSVAR_ASSERT(def_val < my_set_bits64(typelib.count)); >>>>> SYSVAR_ASSERT(strcmp(values[typelib.count-1], "default") == 0); >>>>> SYSVAR_ASSERT(size == sizeof(ulonglong)); >>>>> } >>>>> @@ -1276,7 +1276,7 @@ class Sys_var_flagset: public Sys_var_typelib >>>>> { >>>>> longlong tmp=var->value->val_int(); >>>>> if ((tmp < 0 && ! var->value->unsigned_flag) >>>>> - || (ulonglong)tmp > my_set_bits(typelib.count)) >>>>> + || (ulonglong)tmp > my_set_bits64(typelib.count)) >>>>> return true; >>>>> else >>>>> var->save_result.ulonglong_value= tmp; @@ -1337,7 +1337,7 >>>>> @@ class Sys_var_set: public Sys_var_typelib >>>>> global_var(ulonglong)= def_val; >>>>> SYSVAR_ASSERT(typelib.count > 0); >>>>> SYSVAR_ASSERT(typelib.count <= 64); >>>>> - SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count)); >>>>> + SYSVAR_ASSERT(def_val <= my_set_bits64(typelib.count)); >>>>> SYSVAR_ASSERT(size == sizeof(ulonglong)); >>>>> } >>>>> bool do_check(THD *thd, set_var *var) @@ -1375,7 +1375,7 @@ >>>>> class >>>>> Sys_var_set: public Sys_var_typelib >>>>> { >>>>> longlong tmp=var->value->val_int(); >>>>> if ((tmp < 0 && ! var->value->unsigned_flag) >>>>> - || (ulonglong)tmp > my_set_bits(typelib.count)) >>>>> + || (ulonglong)tmp > my_set_bits64(typelib.count)) >>>>> return true; >>>>> else >>>>> var->save_result.ulonglong_value= tmp; >>>>> -- >>>>> 2.6.3.windows.1 _______________________________________________ Mailing list: https://launchpad.net/~maria-developers Post to : maria-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~maria-developers More help : https://help.launchpad.net/ListHelp