lists.mariadb.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

commits

Thread Start a new thread
Threads by month
  • ----- 2025 -----
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
commits@lists.mariadb.org

  • 14605 discussions
[Commits] 318097b: MDEV-15480 Audit plugin does not respect QUERY_DML for audit plugin.
by holyfoot@askmonty.org 10 May '18

10 May '18
revision-id: 318097bb8f6e12c546b5dcd287416158209dbb39 (mariadb-5.5.60-8-g318097b) parent(s): 1d58d184c2c4ddd8a3b2be6f86d76c4e57bbe14f committer: Alexey Botchkov timestamp: 2018-05-10 19:00:54 +0400 message: MDEV-15480 Audit plugin does not respect QUERY_DML for audit plugin. QUERY_DML_NO_SELECT flag added. --- mysql-test/suite/plugins/r/server_audit.result | 12 +++++++++++ mysql-test/suite/plugins/t/server_audit.test | 7 +++++++ plugin/server_audit/server_audit.c | 29 ++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index 80b4345..2e18a48 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -182,6 +182,17 @@ select 2; 2 2 drop table t1; +set global server_audit_events='query_dml_no_select'; +create table t1(id int); +insert into t1 values (1), (2); +select * from t1; +id +1 +2 +select 2; +2 +2 +drop table t1; set global server_audit_events=''; set global server_audit_query_log_limit= 15; select (1), (2), (3), (4); @@ -332,6 +343,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD \n# comment\nFOR u1 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1=<secret>',ID TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_events=\'\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global serv',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select (1), (2)',0 diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test index 6c5eaff..4af1ed8 100644 --- a/mysql-test/suite/plugins/t/server_audit.test +++ b/mysql-test/suite/plugins/t/server_audit.test @@ -121,6 +121,13 @@ select 2; /*! select 2*/; /*comment*/ select 2; drop table t1; +set global server_audit_events='query_dml_no_select'; +create table t1(id int); +insert into t1 values (1), (2); +select * from t1; +select 2; +drop table t1; + set global server_audit_events=''; set global server_audit_query_log_limit= 15; diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 9a3418e..d27da28 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -15,7 +15,7 @@ #define PLUGIN_VERSION 0x104 -#define PLUGIN_STR_VERSION "1.4.3" +#define PLUGIN_STR_VERSION "1.4.4" #define _my_thread_var loc_thread_var @@ -366,16 +366,17 @@ static MYSQL_SYSVAR_STR(excl_users, excl_users, PLUGIN_VAR_RQCMDARG, /* bits in the event filter. */ #define EVENT_CONNECT 1 #define EVENT_QUERY_ALL 2 -#define EVENT_QUERY 58 +#define EVENT_QUERY 122 #define EVENT_TABLE 4 #define EVENT_QUERY_DDL 8 #define EVENT_QUERY_DML 16 #define EVENT_QUERY_DCL 32 +#define EVENT_QUERY_DML_NO_SELECT 64 static const char *event_names[]= { "CONNECT", "QUERY", "TABLE", "QUERY_DDL", "QUERY_DML", "QUERY_DCL", - NULL + "QUERY_DML_NO_SELECT", NULL }; static TYPELIB events_typelib= { @@ -383,7 +384,7 @@ static TYPELIB events_typelib= }; static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG, "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE," - " QUERY_DDL, QUERY_DML, QUERY_DCL.", + " QUERY_DDL, QUERY_DML, QUERY_DML_NO_SELECT, QUERY_DCL.", NULL, NULL, 0, &events_typelib); #define OUTPUT_SYSLOG 0 #define OUTPUT_FILE 1 @@ -857,6 +858,21 @@ struct sa_keyword dml_keywords[]= }; +struct sa_keyword dml_no_select_keywords[]= +{ + {2, "DO", 0, SQLCOM_DML}, + {4, "CALL", 0, SQLCOM_DML}, + {4, "LOAD", &data_word, SQLCOM_DML}, + {4, "LOAD", &xml_word, SQLCOM_DML}, + {6, "DELETE", 0, SQLCOM_DML}, + {6, "INSERT", 0, SQLCOM_DML}, + {6, "UPDATE", 0, SQLCOM_DML}, + {7, "HANDLER", 0, SQLCOM_DML}, + {7, "REPLACE", 0, SQLCOM_DML}, + {0, NULL, 0, SQLCOM_DML} +}; + + struct sa_keyword dcl_keywords[]= { {6, "CREATE", &user_word, SQLCOM_DCL}, @@ -1637,6 +1653,11 @@ static int log_statement_ex(const struct connection_info *cn, if (filter_query_type(query, dml_keywords)) goto do_log_query; } + if (events & EVENT_QUERY_DML_NO_SELECT) + { + if (filter_query_type(query, dml_no_select_keywords)) + goto do_log_query; + } if (events & EVENT_QUERY_DCL) { if (filter_query_type(query, dcl_keywords))
1 0
0 0
[Commits] eae5844ca04: MDEV-15576: Server crashed in Cached_item_str::cmp / sortcmp or Assertion `item->null_value' failed in Type_handler_temporal_result::make_sort_key upon SELECT with NULLIF and ROLLUP
by Oleksandr Byelkin 09 May '18

09 May '18
revision-id: eae5844ca04c89823cc9ee88095cf89aa45cdb69 (mariadb-10.3.6-127-geae5844ca04) parent(s): 4513de3127df61fa2030690110bb34b7e1c40849 author: Oleksandr Byelkin committer: Oleksandr Byelkin timestamp: 2018-05-09 13:39:13 +0200 message: MDEV-15576: Server crashed in Cached_item_str::cmp / sortcmp or Assertion `item->null_value' failed in Type_handler_temporal_result::make_sort_key upon SELECT with NULLIF and ROLLUP Fix Item_func_rollup_const::get_date to process correctly NULL value. --- mysql-test/main/olap.result | 14 ++++++++++++++ mysql-test/main/olap.test | 17 +++++++++++++++++ sql/item_func.h | 4 +++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/olap.result b/mysql-test/main/olap.result index bcc96d4951d..6fdbe008016 100644 --- a/mysql-test/main/olap.result +++ b/mysql-test/main/olap.result @@ -816,3 +816,17 @@ a int(11) YES 0 b int(20) YES 0 DROP VIEW v1; DROP TABLE t1; +# +# MDEV-15576: Server crashed in Cached_item_str::cmp / sortcmp or +# Assertion `item->null_value' failed in +# Type_handler_temporal_result::make_sort_key upon SELECT with NULLIF +# and ROLLUP +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT NULLIF( CAST( 'foo' AS DATE ), NULL & 'bar' ) AS f FROM t1 GROUP BY f WITH ROLLUP; +f +NULL +NULL +DROP TABLE t1; +# End of 10.3 Tests diff --git a/mysql-test/main/olap.test b/mysql-test/main/olap.test index 3da08581a87..74dbe8ba10b 100644 --- a/mysql-test/main/olap.test +++ b/mysql-test/main/olap.test @@ -447,3 +447,20 @@ DESC v1; DROP VIEW v1; DROP TABLE t1; + +--echo # +--echo # MDEV-15576: Server crashed in Cached_item_str::cmp / sortcmp or +--echo # Assertion `item->null_value' failed in +--echo # Type_handler_temporal_result::make_sort_key upon SELECT with NULLIF +--echo # and ROLLUP +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +--disable_warnings +SELECT NULLIF( CAST( 'foo' AS DATE ), NULL & 'bar' ) AS f FROM t1 GROUP BY f WITH ROLLUP; +--enable_warnings +DROP TABLE t1; + + +--echo # End of 10.3 Tests diff --git a/sql/item_func.h b/sql/item_func.h index 29ff14f7b39..c203a21cc2b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1613,7 +1613,9 @@ class Item_func_rollup_const :public Item_func my_decimal *val_decimal(my_decimal *dec) { return args[0]->val_decimal(dec); } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) { - return args[0]->get_date(ltime, fuzzydate); + bool rc= args[0]->get_date(ltime, fuzzydate); + null_value= rc; + return rc; } const char *func_name() const { return "rollup_const"; } bool const_item() const { return 0; }
1 0
0 0
[Commits] 38cfcd7de13: MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names
by andrei.elkin@pp.inet.fi 09 May '18

09 May '18
revision-id: 38cfcd7de138977a80e116bc3911190ac803af13 (mariadb-10.3.6-81-g38cfcd7de13) parent(s): baa5a43d8cb2f747eeb70d394a362fb5f3fdd194 author: Andrei Elkin committer: Andrei Elkin timestamp: 2018-05-08 22:17:18 +0300 message: MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names Replicated transaction extra gtid statement on slave failed to specify an engine gtid_slave_pos name correctly. In case lower-case-table-names > 0 the InnoDB table name was generated to reproduce the lower-case-table-names=0 version which is of mixed cases. In rpl.rpl_mdev12179 test run this triggered a failure to DROP table which was due to the innodb table handle was not closed: InnoDB: Waited XYZ seconds for ref-count on table: `mysql`.`gtid_slave_pos_innodb` on windows. The closing issue was caused by having the table registered twice in the table cache, for its lower- and mixed- case name versions. The DROP-table handler closed only only one of the cache item to leave the 2nd one active. (On Linux a failure occurs earlier at attempt to open an expected lower-cased table: Last_Error: Error during XID COMMIT: failed to update GTID state in mysql.gtid_slave_pos: 1146: Table 'mysql.gtid_slave_pos_InnoDB' doesn't exist but the table's name as the message shows is not in the right case). Fixed with consulting lower-case-table-names when the engine gtid-slave-pos table is created. Note the lower-case-table-names=a-value created table will not recognized when next the lower case option changes to a different value. --- mysql-test/suite/rpl/r/rpl_mdev12179.result | 21 +++++++++++----- mysql-test/suite/rpl/t/rpl_mdev12179.test | 38 +++++++++++++++++++++++++++-- sql/rpl_rli.cc | 1 + 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_mdev12179.result b/mysql-test/suite/rpl/r/rpl_mdev12179.result index 40059375356..08b1de083af 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev12179.result +++ b/mysql-test/suite/rpl/r/rpl_mdev12179.result @@ -152,12 +152,12 @@ a 1 2 *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created *** -SELECT table_name, engine FROM information_schema.tables +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; -table_name engine +lower(table_name) engine gtid_slave_pos MyISAM -gtid_slave_pos_InnoDB InnoDB +gtid_slave_pos_innodb InnoDB include/stop_slave.inc SET sql_log_bin=0; INSERT INTO mysql.gtid_slave_pos SELECT * FROM mysql.gtid_slave_pos_InnoDB; @@ -245,15 +245,24 @@ a 3 4 *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created *** -SELECT table_name, engine FROM information_schema.tables +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; -table_name engine +lower(table_name) engine gtid_slave_pos MyISAM -gtid_slave_pos_InnoDB InnoDB +gtid_slave_pos_innodb InnoDB SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id max(seq_no) 0 13 +connection server_2; +*** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** +connection server_2; +SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no; +connection server_1; +INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; +include/save_master_gtid.inc +connection server_2; +include/sync_with_master_gtid.inc include/stop_slave.inc SET GLOBAL gtid_pos_auto_engines=""; SET sql_log_bin=0; diff --git a/mysql-test/suite/rpl/t/rpl_mdev12179.test b/mysql-test/suite/rpl/t/rpl_mdev12179.test index a9113c91797..dac1881f40a 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev12179.test +++ b/mysql-test/suite/rpl/t/rpl_mdev12179.test @@ -161,7 +161,8 @@ let $wait_condition= SELECT EXISTS (SELECT * FROM information_schema.tables WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB'); --source include/wait_condition.inc -SELECT table_name, engine FROM information_schema.tables +# MDEV-15373 lowercases 'table_name' to satisfy --lower-case-table-names options +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; @@ -225,7 +226,7 @@ let $wait_condition= SELECT EXISTS (SELECT * FROM information_schema.tables WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB'); --source include/wait_condition.inc -SELECT table_name, engine FROM information_schema.tables +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; @@ -265,6 +266,39 @@ while (!$done) # Note that at this point, the contents of table t2, as well as the GTID # position, is non-deterministic. +# MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names +# This snippet verifies that engine gtid_slave_pos table is found, +# its data are up-to-date. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--connection server_2 +--shutdown_server 30 +--source include/wait_until_disconnected.inc + +--echo *** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc +SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no; + +--connection server_1 +INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +if (`SELECT max(seq_no) <> @seq_no + 1 FROM mysql.gtid_slave_pos_InnoDB`) +{ + SELECT * FROM mysql.gtid_slave_pos_InnoDB; + --die Inconsistent table +} +# +# end of MDEV-15373 #--connection server_2 --source include/stop_slave.inc diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 6229f3e1faf..350c3528f61 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1782,6 +1782,7 @@ gtid_pos_auto_create_tables(rpl_slave_state::gtid_pos_table **list_ptr) p= strmake(p, plugin_name(*auto_engines)->str, FN_REFLEN - (p - buf)); table_name.str= buf; table_name.length= p - buf; + table_case_convert(const_cast<char*>(table_name.str), table_name.length); entry= rpl_global_gtid_slave_state->alloc_gtid_pos_table (&table_name, hton, rpl_slave_state::GTID_POS_AUTO_CREATE); if (!entry)
1 0
0 0
[Commits] 0efb1e5: MDEV-16104 Server crash in JOIN::fix_all_splittings_in_plan
by IgorBabaev 09 May '18

09 May '18
revision-id: 0efb1e502f2b77ae483cc7894beaeaab575e9b6f (mariadb-10.3.6-112-g0efb1e5) parent(s): 0bfd45f63419c45b68448cbd210a6e73e5c1ab34 author: Igor Babaev committer: Igor Babaev timestamp: 2018-05-08 23:32:11 -0700 message: MDEV-16104 Server crash in JOIN::fix_all_splittings_in_plan upon select with view and subqueries This bug occurred when a splittable materialized derived/view were used inside another splittable materialized derived/view. The bug happened because the function JOIN::fix_all_splittings_in_plan() was called at the very beginning of the optimization phase 2 at the moment when the plan structure of the embedding derived/view were not valid. The proper position for this call is the very end of the optimization phase 1. --- mysql-test/main/derived_cond_pushdown.result | 33 ++++++++++++++++++++++++++++ mysql-test/main/derived_cond_pushdown.test | 23 +++++++++++++++++++ sql/sql_select.cc | 15 ++++++++++--- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 82f621c..e178ceb 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -15165,3 +15165,36 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary 2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort drop table t1; +# +# MDEV-16104: embedded splittable materialized derived/views +# +CREATE TABLE t1 (f int PRIMARY KEY) ENGINE=MyISAM; +INSERT INTO t1 +VALUES (3), (7), (1), (4), (8), (5), (9); +CREATE ALGORITHM=MERGE VIEW v1 AS +SELECT a2.* +FROM +( SELECT f, COUNT(*) as c FROM t1 GROUP BY f ) AS a1 +JOIN +t1 AS a2 +USING (f); +EXPLAIN EXTENDED +SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 7 100.00 +2 DERIVED <derived4> ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort +2 DERIVED a2 eq_ref PRIMARY PRIMARY 4 a1.f 1 100.00 Using index +4 DERIVED t1 index PRIMARY PRIMARY 4 NULL 7 100.00 Using index; Using temporary; Using filesort +Warnings: +Note 1003 /* select#1 */ select `s`.`f` AS `f`,`s`.`c` AS `c` from (/* select#2 */ select straight_join `a2`.`f` AS `f`,count(0) AS `c` from ((/* select#4 */ select `test`.`t1`.`f` AS `f`,count(0) AS `c` from `test`.`t1` group by `test`.`t1`.`f`)) `a1` join `test`.`t1` `a2` where `a2`.`f` = `a1`.`f` group by `a2`.`f`) `s` +SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; +f c +1 1 +3 1 +4 1 +5 1 +7 1 +8 1 +9 1 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 2e2ec69..5966412 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -2690,3 +2690,26 @@ eval $q; eval explain $q; drop table t1; + +--echo # +--echo # MDEV-16104: embedded splittable materialized derived/views +--echo # + +CREATE TABLE t1 (f int PRIMARY KEY) ENGINE=MyISAM; +INSERT INTO t1 + VALUES (3), (7), (1), (4), (8), (5), (9); + +CREATE ALGORITHM=MERGE VIEW v1 AS +SELECT a2.* +FROM + ( SELECT f, COUNT(*) as c FROM t1 GROUP BY f ) AS a1 + JOIN + t1 AS a2 + USING (f); + +EXPLAIN EXTENDED +SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; +SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 320e631..c45edf8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1852,6 +1852,18 @@ JOIN::optimize_inner() DBUG_RETURN(1); } + /* + If a splittable materialized derived/view dt_i is embedded into + into another splittable materialized derived/view dt_o then + splitting plans for dt_i and dt_o are evaluated independently. + First the optimizer looks for the best splitting plan sp_i for dt_i. + It happens when non-splitting plans for dt_o are evaluated. + The cost of sp_i is considered as the cost of materialization of dt_i + when evaluating any splitting plan for dt_o. + */ + if (fix_all_splittings_in_plan()) + DBUG_RETURN(1); + setup_subq_exit: with_two_phase_optimization= check_two_phase_optimization(thd); if (with_two_phase_optimization) @@ -9370,9 +9382,6 @@ bool JOIN::get_best_combination() full_join=0; hash_join= FALSE; - if (fix_all_splittings_in_plan()) - DBUG_RETURN(TRUE); - fix_semijoin_strategies_for_picked_join_order(this); JOIN_TAB_RANGE *root_range;
1 0
0 0
[Commits] b2fc197b566: MDEV-15351: wsrep_sst_xtrabackup is broken in 10.1.31
by jan 09 May '18

09 May '18
revision-id: b2fc197b566eb178afa09dd527f8e77a2d9b28de (mariadb-10.1.32-86-gb2fc197b566) parent(s): f98496da969ed2b65f944f11ac11163030bc44b1 author: Jan Lindström committer: Jan Lindström timestamp: 2018-05-09 09:16:20 +0300 message: MDEV-15351: wsrep_sst_xtrabackup is broken in 10.1.31 Remove the setup_ports function call. This is related to https://github.com/MariaDB/server/pull/717 Thanks to Daniel Black and Bart S. --- scripts/wsrep_sst_xtrabackup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 628c1f8b06c..5bf380a8144 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -408,7 +408,6 @@ if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' fi read_cnf -setup_ports get_stream get_transfer
1 0
0 0
[Commits] ce96028: MDEV-16088: Pushdown into materialized views/derived tables doesn't
by galina.shalygina@mariadb.com 08 May '18

08 May '18
revision-id: ce96028f690db1a4371e3846dbfb584c399486cb (mariadb-10.2.14-79-gce96028) parent(s): bd1d152d05ba75bd1bdd2d9bc0358d8508df307a author: Galina Shalygina committer: Galina Shalygina timestamp: 2018-05-08 18:22:38 +0200 message: MDEV-16088: Pushdown into materialized views/derived tables doesn't work in the IN subqueries The pushdown into the materialized derived table/view wasn't done because optimize() for the derived was called before any conditions that can be pushed down were extracted. So optimize() in convert_join_subqueries_to_semijoins() method is called too early and is unnecessary. The second optimize() call in mysql_handle_single_derived() is enough. --- mysql-test/r/derived_cond_pushdown.result | 413 ++++++++++++++++++++++++++++++ mysql-test/r/derived_view.result | 4 +- mysql-test/r/subselect_extra.result | 4 +- mysql-test/t/derived_cond_pushdown.test | 83 ++++++ sql/opt_subselect.cc | 2 - 5 files changed, 500 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result index 8e74e09..09b3b52 100644 --- a/mysql-test/r/derived_cond_pushdown.result +++ b/mysql-test/r/derived_cond_pushdown.result @@ -9045,3 +9045,416 @@ select * from (select date('2018-01-01') as d) as t where t.d between date ('2017-01-01') and date ('2019-01-01'); d 2018-01-01 +# +# MDEV-16088: pushdown into derived defined in the IN subquery +# +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (e INT, f INT, g INT); +INSERT INTO t1 VALUES (1,14),(2,13),(1,19),(2,32),(3,24); +INSERT INTO t2 VALUES (1,19,2),(3,24,1),(1,12,2),(3,11,3),(2,32,1); +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e,d_tab.max_f +FROM ( +SELECT t2.e, MAX(t2.f) AS max_f +FROM t2 +GROUP BY t2.e +HAVING max_f>18 +) as d_tab +WHERE d_tab.e>1 +) +; +a b +2 32 +3 24 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e,d_tab.max_f +FROM ( +SELECT t2.e, MAX(t2.f) AS max_f +FROM t2 +GROUP BY t2.e +HAVING max_f>18 +) as d_tab +WHERE d_tab.e>1 +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 5 Using where +3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e,d_tab.max_f +FROM ( +SELECT t2.e, MAX(t2.f) AS max_f +FROM t2 +GROUP BY t2.e +HAVING max_f>18 +) as d_tab +WHERE d_tab.e>1 +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "max_f"], + "ref": ["func", "func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_f > 18", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "t2.e > 1" + } + } + } + } + } + } + } + } + } + } +} +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e,d_tab.max_f +FROM ( +SELECT t2.e, MAX(t2.f) AS max_f +FROM t2 +GROUP BY t2.e +HAVING max_f>18 +) as d_tab +WHERE d_tab.max_f<25 +) +; +a b +1 19 +3 24 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e,d_tab.max_f +FROM ( +SELECT t2.e, MAX(t2.f) AS max_f +FROM t2 +GROUP BY t2.e +HAVING max_f>18 +) as d_tab +WHERE d_tab.max_f<25 +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 5 Using where +3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e,d_tab.max_f +FROM ( +SELECT t2.e, MAX(t2.f) AS max_f +FROM t2 +GROUP BY t2.e +HAVING max_f>18 +) as d_tab +WHERE d_tab.max_f<25 +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "max_f"], + "ref": ["func", "func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "d_tab.max_f < 25", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_f > 18 and max_f < 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + } + } + } + } + } + } + } + } + } + } +} +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e, MAX(d_tab.max_f) AS max_f +FROM ( +SELECT t2.e, MAX(t2.f) as max_f, t2.g +FROM t2 +GROUP BY t2.e +) as d_tab +WHERE d_tab.e>1 +GROUP BY d_tab.g +) +; +a b +2 32 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e, MAX(d_tab.max_f) AS max_f +FROM ( +SELECT t2.e, MAX(t2.f) as max_f, t2.g +FROM t2 +GROUP BY t2.e +) as d_tab +WHERE d_tab.e>1 +GROUP BY d_tab.g +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 5 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e, MAX(d_tab.max_f) AS max_f +FROM ( +SELECT t2.e, MAX(t2.f) as max_f, t2.g +FROM t2 +GROUP BY t2.e +) as d_tab +WHERE d_tab.e>1 +GROUP BY d_tab.g +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "t1.a is not null and t1.b is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "max_f"], + "ref": ["test.t1.a", "test.t1.b"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "t2.e > 1" + } + } + } + } + } + } + } + } + } + } + } +} +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e, MAX(d_tab.max_f) AS max_f +FROM ( +SELECT t2.e, MAX(t2.f) as max_f, t2.g +FROM t2 +GROUP BY t2.e +) as d_tab +WHERE d_tab.max_f>20 +GROUP BY d_tab.g +) +; +a b +2 32 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e, MAX(d_tab.max_f) AS max_f +FROM ( +SELECT t2.e, MAX(t2.f) as max_f, t2.g +FROM t2 +GROUP BY t2.e +) as d_tab +WHERE d_tab.max_f>20 +GROUP BY d_tab.g +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 5 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a,t1.b) IN +( +SELECT d_tab.e, MAX(d_tab.max_f) AS max_f +FROM ( +SELECT t2.e, MAX(t2.f) as max_f, t2.g +FROM t2 +GROUP BY t2.e +) as d_tab +WHERE d_tab.max_f>20 +GROUP BY d_tab.g +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "t1.a is not null and t1.b is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "max_f"], + "ref": ["test.t1.a", "test.t1.b"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "d_tab.max_f > 20", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_f > 20", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + } + } + } + } + } + } + } + } + } + } + } +} +DROP TABLE t1,t2; diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index df6ba08..d2804ce 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -1841,7 +1841,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 system NULL NULL NULL NULL 1 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY <derived3> ALL NULL NULL NULL NULL 3 Using where; Start temporary; End temporary -3 DERIVED t1 ALL NULL NULL NULL NULL 3 +3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using where SELECT * FROM t3 WHERE t3.b IN (SELECT v1.b FROM v1, t2 WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c); @@ -1856,7 +1856,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 system NULL NULL NULL NULL 1 1 PRIMARY <derived3> ref key1 key1 8 const,const 0 Start temporary 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join) -3 DERIVED t1 ALL NULL NULL NULL NULL 3 +3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using where SELECT * FROM t3 WHERE t3.b IN (SELECT v1.b FROM v1, t2 WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c); diff --git a/mysql-test/r/subselect_extra.result b/mysql-test/r/subselect_extra.result index 73642c0..a3a0f1f 100644 --- a/mysql-test/r/subselect_extra.result +++ b/mysql-test/r/subselect_extra.result @@ -434,7 +434,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 system NULL NULL NULL NULL 1 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY <derived3> ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t3); Using join buffer (flat, BNL join) -3 DERIVED t1 ALL NULL NULL NULL NULL 3 +3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using where SELECT * FROM t3 WHERE t3.b IN (SELECT v1.b FROM v1, t2 WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c); @@ -449,7 +449,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 system NULL NULL NULL NULL 1 1 PRIMARY <derived3> ref key1 key1 8 const,const 0 Start temporary 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join) -3 DERIVED t1 ALL NULL NULL NULL NULL 3 +3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using where SELECT * FROM t3 WHERE t3.b IN (SELECT v1.b FROM v1, t2 WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c); diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test index 0b87738..e8f6e9c 100644 --- a/mysql-test/t/derived_cond_pushdown.test +++ b/mysql-test/t/derived_cond_pushdown.test @@ -1646,3 +1646,86 @@ select * from (select date('2018-01-01') as d select * from (select date('2018-01-01') as d) as t where t.d between date ('2017-01-01') and date ('2019-01-01'); + +--echo # +--echo # MDEV-16088: pushdown into derived defined in the IN subquery +--echo # + +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (e INT, f INT, g INT); +INSERT INTO t1 VALUES (1,14),(2,13),(1,19),(2,32),(3,24); +INSERT INTO t2 VALUES (1,19,2),(3,24,1),(1,12,2),(3,11,3),(2,32,1); + +LET $query= +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN + ( + SELECT d_tab.e,d_tab.max_f + FROM ( + SELECT t2.e, MAX(t2.f) AS max_f + FROM t2 + GROUP BY t2.e + HAVING max_f>18 + ) as d_tab + WHERE d_tab.e>1 + ) +; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +LET $query= +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN + ( + SELECT d_tab.e,d_tab.max_f + FROM ( + SELECT t2.e, MAX(t2.f) AS max_f + FROM t2 + GROUP BY t2.e + HAVING max_f>18 + ) as d_tab + WHERE d_tab.max_f<25 + ) +; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +LET $query= +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN + ( + SELECT d_tab.e, MAX(d_tab.max_f) AS max_f + FROM ( + SELECT t2.e, MAX(t2.f) as max_f, t2.g + FROM t2 + GROUP BY t2.e + ) as d_tab + WHERE d_tab.e>1 + GROUP BY d_tab.g + ) +; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +LET $query= +SELECT * FROM t1 +WHERE (t1.a,t1.b) IN + ( + SELECT d_tab.e, MAX(d_tab.max_f) AS max_f + FROM ( + SELECT t2.e, MAX(t2.f) as max_f, t2.g + FROM t2 + GROUP BY t2.e + ) as d_tab + WHERE d_tab.max_f>20 + GROUP BY d_tab.g + ) +; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +DROP TABLE t1,t2; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index b28adae..5765278 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1092,8 +1092,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) while ((in_subq= li++)) { SELECT_LEX *subq_sel= in_subq->get_select_lex(); - if (subq_sel->handle_derived(thd->lex, DT_OPTIMIZE)) - DBUG_RETURN(1); if (subq_sel->handle_derived(thd->lex, DT_MERGE)) DBUG_RETURN(TRUE); subq_sel->update_used_tables();
1 0
0 0
[Commits] 46e0c8a9219: MDEV-11071: Assertion `thd->transaction.stmt.is_empty()' failed in Locked_tables_list::unlock_locked_table
by Oleksandr Byelkin 08 May '18

08 May '18
revision-id: 46e0c8a921978e7b95adf3f17f3c85b18d9f9ef6 (mariadb-10.2.14-78-g46e0c8a9219) parent(s): 9bcd0f5fea8ca26742b10d37b95a966c69909ff1 author: Oleksandr Byelkin committer: Oleksandr Byelkin timestamp: 2018-05-08 15:26:26 +0200 message: MDEV-11071: Assertion `thd->transaction.stmt.is_empty()' failed in Locked_tables_list::unlock_locked_table fix_length_and_dec now return result (error/OK) --- mysql-test/r/alter_table.result | 11 +++ mysql-test/t/alter_table.test | 16 ++++ sql/item.h | 2 +- sql/item_cmpfunc.cc | 106 ++++++++++++++++---------- sql/item_cmpfunc.h | 58 ++++++++------ sql/item_func.cc | 106 +++++++++++++++----------- sql/item_func.h | 118 ++++++++++++++++------------- sql/item_geofunc.cc | 9 ++- sql/item_geofunc.h | 72 ++++++++++-------- sql/item_inetfunc.h | 12 ++- sql/item_jsonfunc.cc | 57 +++++++++----- sql/item_jsonfunc.h | 38 +++++----- sql/item_strfunc.cc | 164 +++++++++++++++++++++++++--------------- sql/item_strfunc.h | 156 +++++++++++++++++++++++--------------- sql/item_subselect.cc | 19 +++-- sql/item_subselect.h | 8 +- sql/item_sum.cc | 28 +++---- sql/item_sum.h | 30 ++++---- sql/item_timefunc.cc | 46 ++++++----- sql/item_timefunc.h | 125 +++++++++++++++++------------- sql/item_windowfunc.cc | 6 +- sql/item_windowfunc.h | 9 ++- sql/item_xmlfunc.cc | 13 ++-- sql/item_xmlfunc.h | 2 +- sql/sql_select.cc | 3 +- sql/sql_table.cc | 11 ++- 26 files changed, 734 insertions(+), 491 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 0845459f6b6..5f5586e2c21 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -2309,5 +2309,16 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; # +# MDEV-11071: Assertion `thd->transaction.stmt.is_empty()' failed +# in Locked_tables_list::unlock_locked_tables +# +CREATE TABLE t1 (d DATETIME DEFAULT CURRENT_TIMESTAMP, i INT) ENGINE=InnoDB; +INSERT INTO t1 (i) VALUES (1),(1); +LOCK TABLE t1 WRITE; +ALTER TABLE t1 ADD UNIQUE(i); +ERROR 23000: Duplicate entry '1' for key 'i' +UNLOCK TABLES; +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 63d24c0740d..0a683b48338 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1900,6 +1900,22 @@ alter table t1 change b new_b int not null, add column b char(1), add constraint show create table t1; drop table t1; +--echo # +--echo # MDEV-11071: Assertion `thd->transaction.stmt.is_empty()' failed +--echo # in Locked_tables_list::unlock_locked_tables +--echo # + +CREATE TABLE t1 (d DATETIME DEFAULT CURRENT_TIMESTAMP, i INT) ENGINE=InnoDB; +INSERT INTO t1 (i) VALUES (1),(1); +LOCK TABLE t1 WRITE; +--error ER_DUP_ENTRY +ALTER TABLE t1 ADD UNIQUE(i); + +# Cleanup +UNLOCK TABLES; +DROP TABLE t1; + + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/item.h b/sql/item.h index 8921ee76f6a..e9713730a1c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4210,7 +4210,7 @@ class Item_func_or_sum: public Item_result_field, also to make printing of items inherited from Item_sum uniform. */ virtual const char *func_name() const= 0; - virtual void fix_length_and_dec()= 0; + virtual bool fix_length_and_dec()= 0; bool const_item() const { return const_item_cache; } table_map used_tables() const { return used_tables_cache; } Item* build_clone(THD *thd, MEM_ROOT *mem_root); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 44cc4f3cae9..46cf412e229 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -526,7 +526,7 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) } -void Item_bool_rowready_func2::fix_length_and_dec() +bool Item_bool_rowready_func2::fix_length_and_dec() { max_length= 1; // Function returns 0 or 1 @@ -535,8 +535,9 @@ void Item_bool_rowready_func2::fix_length_and_dec() we have to check for out of memory conditions here */ if (!args[0] || !args[1]) - return; - setup_args_and_comparator(current_thd, &cmp); + return FALSE; + bool res= setup_args_and_comparator(current_thd, &cmp); + return res; } @@ -1156,12 +1157,13 @@ int Arg_comparator::compare_e_str_json() } -void Item_func_truth::fix_length_and_dec() +bool Item_func_truth::fix_length_and_dec() { maybe_null= 0; null_value= 0; decimals= 0; max_length= 1; + return FALSE; } @@ -1778,10 +1780,11 @@ longlong Item_func_eq::val_int() /** Same as Item_func_eq, but NULL = NULL. */ -void Item_func_equal::fix_length_and_dec() +bool Item_func_equal::fix_length_and_dec() { - Item_bool_rowready_func2::fix_length_and_dec(); + bool rc= Item_bool_rowready_func2::fix_length_and_dec(); maybe_null=null_value=0; + return rc; } longlong Item_func_equal::val_int() @@ -1878,7 +1881,7 @@ bool Item_func_interval::fix_fields(THD *thd, Item **ref) } -void Item_func_interval::fix_length_and_dec() +bool Item_func_interval::fix_length_and_dec() { uint rows= row->cols(); @@ -1896,10 +1899,13 @@ void Item_func_interval::fix_length_and_dec() not_null_consts&= el->const_item() && !el->is_null(); } - if (not_null_consts && - (intervals= (interval_range*) current_thd->alloc(sizeof(interval_range) * - (rows - 1)))) + if (not_null_consts) { + intervals= (interval_range*) current_thd->alloc(sizeof(interval_range) * + (rows - 1)); + if (!intervals) + return TRUE; + if (use_decimal_comparison) { for (uint i= 1; i < rows; i++) @@ -1939,6 +1945,7 @@ void Item_func_interval::fix_length_and_dec() not_null_tables_cache= row->not_null_tables(); with_sum_func= with_sum_func || row->with_sum_func; with_field= with_field || row->with_field; + return FALSE; } @@ -2099,7 +2106,7 @@ void Item_func_between::fix_after_pullout(st_select_lex *new_parent, eval_not_null_tables(NULL); } -void Item_func_between::fix_length_and_dec() +bool Item_func_between::fix_length_and_dec() { THD *thd= current_thd; max_length= 1; @@ -2110,13 +2117,13 @@ void Item_func_between::fix_length_and_dec() we have to check for out of memory conditions here */ if (!args[0] || !args[1] || !args[2]) - return; + return TRUE; if (agg_cmp_type(&m_compare_type, args, 3)) - return; + return TRUE; if (m_compare_type == STRING_RESULT && agg_arg_charsets_for_comparison(cmp_collation, args, 3)) - return; + return TRUE; /* When comparing as date/time, we need to convert non-temporal values @@ -2141,6 +2148,7 @@ void Item_func_between::fix_length_and_dec() m_compare_type= INT_RESULT; // Works for all types. } } + return FALSE; } @@ -2438,7 +2446,7 @@ void Item_func_if::cache_type_info(Item *source) } -void +bool Item_func_if::fix_length_and_dec() { // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr. @@ -2449,15 +2457,15 @@ Item_func_if::fix_length_and_dec() // If both arguments are NULL, make resulting type BINARY(0). if (args[2]->type() == NULL_ITEM) set_handler_by_field_type(MYSQL_TYPE_STRING); - return; + return FALSE; } if (args[2]->type() == NULL_ITEM) { cache_type_info(args[1]); maybe_null= true; - return; + return FALSE; } - Item_func_case_abbreviation2::fix_length_and_dec2(args + 1); + return Item_func_case_abbreviation2::fix_length_and_dec2(args + 1); } @@ -2571,7 +2579,7 @@ void Item_func_nullif::update_used_tables() -void +bool Item_func_nullif::fix_length_and_dec() { /* @@ -2721,6 +2729,8 @@ Item_func_nullif::fix_length_and_dec() m_cache= args[0]->cmp_type() == STRING_RESULT ? new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) : Item_cache::get_cache(thd, args[0]); + if (!m_cache) + return TRUE; m_cache->setup(thd, args[0]); m_cache->store(args[0]); m_cache->set_used_tables(args[0]->used_tables()); @@ -2734,7 +2744,8 @@ Item_func_nullif::fix_length_and_dec() fix_char_length(args[2]->max_char_length()); maybe_null=1; m_arg0= args[0]; - setup_args_and_comparator(thd, &cmp); + if (setup_args_and_comparator(thd, &cmp)) + return TRUE; /* A special code for EXECUTE..PREPARE. @@ -2774,6 +2785,7 @@ Item_func_nullif::fix_length_and_dec() */ if (args[0] == m_arg0) m_arg0= NULL; + return FALSE; } @@ -3155,7 +3167,7 @@ static void change_item_tree_if_needed(THD *thd, Item **place, Item *new_value) } -void Item_func_case::fix_length_and_dec() +bool Item_func_case::fix_length_and_dec() { m_found_types= 0; if (else_expr_num == -1 || args[else_expr_num]->maybe_null) @@ -3172,7 +3184,7 @@ void Item_func_case::fix_length_and_dec() if (Item_func_case::result_type() == STRING_RESULT) { if (count_string_result_length(Item_func_case::field_type(), rets, nrets)) - return; + return TRUE; } else fix_attributes(rets, nrets); @@ -3186,7 +3198,7 @@ void Item_func_case::fix_length_and_dec() left_cmp_type= args[0]->cmp_type(); if (!(m_found_types= collect_cmp_types(args, nwhens + 1))) - return; + return TRUE; Item *date_arg= 0; if (m_found_types & (1U << TIME_RESULT)) @@ -3219,7 +3231,7 @@ void Item_func_case::fix_length_and_dec() CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END */ if (agg_arg_charsets_for_comparison(cmp_collation, args, nwhens + 1)) - return; + return TRUE; } for (uint i= 0; i <= (uint)TIME_RESULT; i++) @@ -3230,10 +3242,11 @@ void Item_func_case::fix_length_and_dec() if (!(cmp_items[i]= cmp_item::get_comparator((Item_result)i, date_arg, cmp_collation.collation))) - return; + return TRUE; } } } + return FALSE; } @@ -4114,7 +4127,7 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) (uchar *) y->ptr(),y->length()); } -void Item_func_in::fix_length_and_dec() +bool Item_func_in::fix_length_and_dec() { Item **arg, **arg_end; bool const_itm= 1; @@ -4126,7 +4139,7 @@ void Item_func_in::fix_length_and_dec() m_compare_type= STRING_RESULT; left_cmp_type= args[0]->cmp_type(); if (!(found_types= collect_cmp_types(args, arg_count, true))) - return; + return TRUE; for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++) { @@ -4175,7 +4188,7 @@ void Item_func_in::fix_length_and_dec() { if (m_compare_type == STRING_RESULT && agg_arg_charsets_for_comparison(cmp_collation, args, arg_count)) - return; + return TRUE; arg_types_compatible= TRUE; if (m_compare_type == ROW_RESULT) @@ -4186,12 +4199,14 @@ void Item_func_in::fix_length_and_dec() if (bisection_possible) { array= new (thd->mem_root) in_row(thd, arg_count-1, 0); + if (!array) + return TRUE; cmp= &((in_row*)array)->tmp; } else { if (!(cmp= new (thd->mem_root) cmp_item_row)) - return; + return TRUE; cmp_items[ROW_RESULT]= cmp; } cmp->n= cols; @@ -4208,6 +4223,8 @@ void Item_func_in::fix_length_and_dec() else cmp= ((cmp_item_row*)cmp_items[ROW_RESULT])->comparators + col; *cmp= new (thd->mem_root) cmp_item_datetime(date_arg); + if (!(*cmp)) + return TRUE; } } } @@ -4270,7 +4287,7 @@ void Item_func_in::fix_length_and_dec() break; } if (!array || thd->is_fatal_error) // OOM - return; + return TRUE; uint j=0; for (uint i=1 ; i < arg_count ; i++) { @@ -4295,7 +4312,7 @@ void Item_func_in::fix_length_and_dec() date_arg= find_date_time_item(thd, args, arg_count, 0, true); if (found_types & (1U << STRING_RESULT) && agg_arg_charsets_for_comparison(cmp_collation, args, arg_count)) - return; + return TRUE; for (i= 0; i <= (uint) TIME_RESULT; i++) { if (found_types & (1U << i) && !cmp_items[i]) @@ -4303,11 +4320,12 @@ void Item_func_in::fix_length_and_dec() if (!cmp_items[i] && !(cmp_items[i]= cmp_item::get_comparator((Item_result)i, date_arg, cmp_collation.collation))) - return; + return TRUE; } } } max_length= 1; + return FALSE; } @@ -4576,7 +4594,8 @@ Item_cond::fix_fields(THD *thd, Item **ref) with_window_func|= item->with_window_func; maybe_null|= item->maybe_null; } - fix_length_and_dec(); + if (fix_length_and_dec()) + return TRUE; fixed= 1; return FALSE; } @@ -5609,16 +5628,16 @@ bool Item_func_regex::fix_fields(THD *thd, Item **ref) return Item_bool_func::fix_fields(thd, ref); } -void +bool Item_func_regex::fix_length_and_dec() { - Item_bool_func::fix_length_and_dec(); - - if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) - return; + if (Item_bool_func::fix_length_and_dec() || + agg_arg_charsets_for_comparison(cmp_collation, args, 2)) + return TRUE; re.init(cmp_collation.collation, 0); re.fix_owner(this, args[0], args[1]); + return FALSE; } @@ -5642,14 +5661,15 @@ bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref) } -void +bool Item_func_regexp_instr::fix_length_and_dec() { if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) - return; + return TRUE; re.init(cmp_collation.collation, 0); re.fix_owner(this, args[0], args[1]); + return FALSE; } @@ -6591,7 +6611,8 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) } if (prev_equal_field && last_equal_field != first_equal_field) last_equal_field->next_equal_field= first_equal_field; - fix_length_and_dec(); + if (fix_length_and_dec()) + return TRUE; fixed= 1; return FALSE; } @@ -6677,11 +6698,12 @@ longlong Item_equal::val_int() } -void Item_equal::fix_length_and_dec() +bool Item_equal::fix_length_and_dec() { Item *item= get_first(NO_PARTICULAR_TAB, NULL); eval_item= cmp_item::get_comparator(item->cmp_type(), item, item->collation.collation); + return FALSE; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index de1b27cff1a..5efb98bc81d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -200,7 +200,7 @@ class Item_bool_func :public Item_int_func Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {} bool is_bool_type() { return true; } virtual CHARSET_INFO *compare_collation() const { return NULL; } - void fix_length_and_dec() { decimals=0; max_length=1; } + bool fix_length_and_dec() { decimals=0; max_length=1; return FALSE; } uint decimal_precision() const { return 1; } bool need_parentheses_in_default() { return true; } }; @@ -216,7 +216,7 @@ class Item_func_truth : public Item_bool_func public: virtual bool val_bool(); virtual longlong val_int(); - virtual void fix_length_and_dec(); + virtual bool fix_length_and_dec(); virtual void print(String *str, enum_query_type query_type); enum precedence precedence() const { return CMP_PRECEDENCE; } @@ -501,7 +501,7 @@ class Item_bool_rowready_func2 :public Item_bool_func2_with_rev cond); return this; } - void fix_length_and_dec(); + bool fix_length_and_dec(); int set_cmp_func() { return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true); @@ -711,7 +711,7 @@ class Item_func_equal :public Item_bool_rowready_func2 Item_func_equal(THD *thd, Item *a, Item *b): Item_bool_rowready_func2(thd, a, b) {} longlong val_int(); - void fix_length_and_dec(); + bool fix_length_and_dec(); table_map not_null_tables() const { return 0; } enum Functype functype() const { return EQUAL_FUNC; } enum Functype rev_functype() const { return EQUAL_FUNC; } @@ -878,7 +878,7 @@ class Item_func_between :public Item_func_opt_neg enum Functype functype() const { return BETWEEN; } const char *func_name() const { return "between"; } enum precedence precedence() const { return BETWEEN_PRECEDENCE; } - void fix_length_and_dec(); + bool fix_length_and_dec(); virtual void print(String *str, enum_query_type query_type); bool eval_not_null_tables(void *opt_arg); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); @@ -911,10 +911,12 @@ class Item_func_strcmp :public Item_int_func longlong val_int(); uint decimal_precision() const { return 1; } const char *func_name() const { return "strcmp"; } - void fix_length_and_dec() + bool fix_length_and_dec() { - agg_arg_charsets_for_comparison(cmp_collation, args, 2); + if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) + return TRUE; fix_char_length(2); // returns "1" or "0" or "-1" + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_strcmp>(thd, mem_root, this); } @@ -941,7 +943,7 @@ class Item_func_interval :public Item_int_func } bool fix_fields(THD *, Item **); longlong val_int(); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "interval"; } uint decimal_precision() const { return 2; } void print(String *str, enum_query_type query_type) @@ -966,10 +968,11 @@ class Item_func_coalesce :public Item_func_hybrid_field_type String *str_op(String *); my_decimal *decimal_op(my_decimal *); bool date_op(MYSQL_TIME *ltime,uint fuzzydate); - void fix_length_and_dec() + bool fix_length_and_dec() { set_handler_by_field_type(agg_field_type(args, arg_count, true)); fix_attributes(args, arg_count); + return FALSE; } const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } @@ -986,10 +989,11 @@ class Item_func_coalesce :public Item_func_hybrid_field_type class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type { protected: - void fix_length_and_dec2(Item **items) + bool fix_length_and_dec2(Item **items) { set_handler_by_field_type(agg_field_type(items, 2, true)); fix_attributes(items, 2); + return FALSE; } uint decimal_precision2(Item **args) const; public: @@ -1010,10 +1014,12 @@ class Item_func_ifnull :public Item_func_case_abbreviation2 String *str_op(String *str); my_decimal *decimal_op(my_decimal *); bool date_op(MYSQL_TIME *ltime,uint fuzzydate); - void fix_length_and_dec() + bool fix_length_and_dec() { - Item_func_case_abbreviation2::fix_length_and_dec2(args); + if (Item_func_case_abbreviation2::fix_length_and_dec2(args)) + return TRUE; maybe_null= args[1]->maybe_null; + return FALSE; } const char *func_name() const { return "ifnull"; } Field *create_field_for_create_select(TABLE *table) @@ -1041,7 +1047,7 @@ class Item_func_if :public Item_func_case_abbreviation2 my_decimal *decimal_op(my_decimal *); String *str_op(String *); bool fix_fields(THD *, Item **); - void fix_length_and_dec(); + bool fix_length_and_dec(); uint decimal_precision() const { return Item_func_case_abbreviation2::decimal_precision2(args + 1); @@ -1108,7 +1114,7 @@ class Item_func_nullif :public Item_func_hybrid_field_type longlong int_op(); String *str_op(String *str); my_decimal *decimal_op(my_decimal *); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool walk(Item_processor processor, bool walk_subquery, void *arg); uint decimal_precision() const { return args[2]->decimal_precision(); } const char *func_name() const { return "nullif"; } @@ -1570,7 +1576,7 @@ class Item_func_case :public Item_func_hybrid_field_type my_decimal *decimal_op(my_decimal *); bool date_op(MYSQL_TIME *ltime, uint fuzzydate); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); uint decimal_precision() const; table_map not_null_tables() const { return 0; } const char *func_name() const { return "case"; } @@ -1648,7 +1654,7 @@ class Item_func_in :public Item_func_opt_neg } longlong val_int(); bool fix_fields(THD *, Item **); - void fix_length_and_dec(); + bool fix_length_and_dec(); void cleanup() { uint i; @@ -1718,7 +1724,7 @@ class cmp_item_row :public cmp_item int compare(cmp_item *arg); cmp_item *make_same(); void store_value_by_template(THD *thd, cmp_item *tmpl, Item *); - friend void Item_func_in::fix_length_and_dec(); + friend bool Item_func_in::fix_length_and_dec(); cmp_item *get_comparator(uint i) { return comparators[i]; } }; @@ -1731,7 +1737,7 @@ class in_row :public in_vector ~in_row(); void set(uint pos,Item *item); uchar *get_value(Item *item); - friend void Item_func_in::fix_length_and_dec(); + friend bool Item_func_in::fix_length_and_dec(); Item_result result_type() { return ROW_RESULT; } cmp_item *get_cmp_item() { return &tmp; } }; @@ -1763,7 +1769,11 @@ class Item_func_null_predicate :public Item_bool_func } CHARSET_INFO *compare_collation() const { return args[0]->collation.collation; } - void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; } + bool fix_length_and_dec() + { + decimals=0; max_length=1; maybe_null=0; + return FALSE; + } bool count_sargable_conds(void *arg); }; @@ -1987,10 +1997,10 @@ class Item_func_like :public Item_bool_func2 const char *func_name() const { return "like"; } enum precedence precedence() const { return CMP_PRECEDENCE; } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec() + bool fix_length_and_dec() { max_length= 1; - agg_arg_charsets_for_comparison(cmp_collation, args, 2); + return agg_arg_charsets_for_comparison(cmp_collation, args, 2); } void cleanup(); @@ -2111,7 +2121,7 @@ class Item_func_regex :public Item_bool_func } longlong val_int(); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "regexp"; } enum precedence precedence() const { return CMP_PRECEDENCE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -2149,7 +2159,7 @@ class Item_func_regexp_instr :public Item_int_func } longlong val_int(); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "regexp_instr"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_regexp_instr>(thd, mem_root, this); } @@ -2385,7 +2395,7 @@ class Item_equal: public Item_bool_func longlong val_int(); const char *func_name() const { return "multiple equal"; } void sort(Item_field_cmpfunc compare, void *arg); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool fix_fields(THD *thd, Item **ref); void cleanup() { diff --git a/sql/item_func.cc b/sql/item_func.cc index 0c239b54f30..255923d98dd 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -235,8 +235,7 @@ Item_func::fix_fields(THD *thd, Item **ref) with_subselect|= item->has_subquery(); } } - fix_length_and_dec(); - if (thd->is_error()) // An error inside fix_length_and_dec occurred + if (fix_length_and_dec()) return TRUE; fixed= 1; return FALSE; @@ -731,10 +730,12 @@ String *Item_int_func::val_str(String *str) } -void Item_func_connection_id::fix_length_and_dec() +bool Item_func_connection_id::fix_length_and_dec() { - Item_int_func::fix_length_and_dec(); + if (Item_int_func::fix_length_and_dec()) + return TRUE; max_length= 10; + return FALSE; } @@ -753,7 +754,7 @@ bool Item_func_connection_id::fix_fields(THD *thd, Item **ref) function of two arguments. */ -void Item_num_op::fix_length_and_dec(void) +bool Item_num_op::fix_length_and_dec(void) { DBUG_ENTER("Item_num_op::fix_length_and_dec"); DBUG_PRINT("info", ("name %s", func_name())); @@ -789,7 +790,7 @@ void Item_num_op::fix_length_and_dec(void) result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" : result_type() == INT_RESULT ? "INT_RESULT" : "--ILLEGAL!!!--"))); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -799,7 +800,7 @@ void Item_num_op::fix_length_and_dec(void) type depends only on the first argument) */ -void Item_func_num1::fix_length_and_dec() +bool Item_func_num1::fix_length_and_dec() { DBUG_ENTER("Item_func_num1::fix_length_and_dec"); DBUG_PRINT("info", ("name %s", func_name())); @@ -830,7 +831,7 @@ void Item_func_num1::fix_length_and_dec() result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" : result_type() == INT_RESULT ? "INT_RESULT" : "--ILLEGAL!!!--"))); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -1415,12 +1416,14 @@ void Item_func_additive_op::result_precision() subtraction of UNSIGNED BIGINT to return negative values. */ -void Item_func_minus::fix_length_and_dec() +bool Item_func_minus::fix_length_and_dec() { - Item_num_op::fix_length_and_dec(); + if (Item_num_op::fix_length_and_dec()) + return TRUE; if (unsigned_flag && (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION)) unsigned_flag=0; + return FALSE; } @@ -1718,11 +1721,12 @@ void Item_func_div::result_precision() } -void Item_func_div::fix_length_and_dec() +bool Item_func_div::fix_length_and_dec() { DBUG_ENTER("Item_func_div::fix_length_and_dec"); prec_increment= current_thd->variables.div_precincrement; - Item_num_op::fix_length_and_dec(); + if (Item_num_op::fix_length_and_dec()) + DBUG_RETURN(TRUE); switch (Item_func_div::result_type()) { case REAL_RESULT: { @@ -1753,7 +1757,7 @@ void Item_func_div::fix_length_and_dec() DBUG_ASSERT(0); } maybe_null= 1; // devision by zero - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -1829,7 +1833,7 @@ longlong Item_func_int_div::val_int() } -void Item_func_int_div::fix_length_and_dec() +bool Item_func_int_div::fix_length_and_dec() { Item_result argtype= args[0]->result_type(); /* use precision ony for the data type it is applicable for and valid */ @@ -1840,6 +1844,7 @@ void Item_func_int_div::fix_length_and_dec() MY_INT64_NUM_DECIMAL_DIGITS : char_length); maybe_null=1; unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag; + return false; } @@ -1923,11 +1928,13 @@ void Item_func_mod::result_precision() } -void Item_func_mod::fix_length_and_dec() +bool Item_func_mod::fix_length_and_dec() { - Item_num_op::fix_length_and_dec(); + if (Item_num_op::fix_length_and_dec()) + return true; maybe_null= 1; unsigned_flag= args[0]->unsigned_flag; + return false; } @@ -1974,10 +1981,11 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value) } -void Item_func_neg::fix_length_and_dec() +bool Item_func_neg::fix_length_and_dec() { DBUG_ENTER("Item_func_neg::fix_length_and_dec"); - Item_func_num1::fix_length_and_dec(); + if (Item_func_num1::fix_length_and_dec()) + DBUG_RETURN(TRUE); /* 1 add because sign can appear */ max_length= args[0]->max_length + 1; @@ -2003,7 +2011,7 @@ void Item_func_neg::fix_length_and_dec() } } unsigned_flag= 0; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -2043,10 +2051,12 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) } -void Item_func_abs::fix_length_and_dec() +bool Item_func_abs::fix_length_and_dec() { - Item_func_num1::fix_length_and_dec(); + if (Item_func_num1::fix_length_and_dec()) + return TRUE; unsigned_flag= args[0]->unsigned_flag; + return FALSE; } @@ -2278,7 +2288,7 @@ longlong Item_func_bit_neg::val_int() // Conversion functions -void Item_func_int_val::fix_length_and_dec() +bool Item_func_int_val::fix_length_and_dec() { DBUG_ENTER("Item_func_int_val::fix_length_and_dec"); DBUG_PRINT("info", ("name %s", func_name())); @@ -2326,7 +2336,7 @@ void Item_func_int_val::fix_length_and_dec() result_type() == INT_RESULT ? "INT_RESULT" : "--ILLEGAL!!!--"))); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -2424,7 +2434,7 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) } -void Item_func_round::fix_length_and_dec() +bool Item_func_round::fix_length_and_dec() { int decimals_to_set; longlong val1; @@ -2442,12 +2452,12 @@ void Item_func_round::fix_length_and_dec() } else set_handler_by_result_type(REAL_RESULT); - return; + return FALSE; } val1= args[1]->val_int(); if ((null_value= args[1]->null_value)) - return; + return FALSE; val1_unsigned= args[1]->unsigned_flag; if (val1 < 0) @@ -2460,7 +2470,7 @@ void Item_func_round::fix_length_and_dec() decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC); max_length= float_length(decimals); set_handler_by_result_type(REAL_RESULT); - return; + return FALSE; } switch (args[0]->result_type()) { @@ -2501,6 +2511,7 @@ void Item_func_round::fix_length_and_dec() case TIME_RESULT: DBUG_ASSERT(0); /* This result type isn't handled */ } + return FALSE; } double my_double_round(double value, longlong dec, bool dec_unsigned, @@ -2725,7 +2736,7 @@ double Item_func_units::val_real() } -void Item_func_min_max::fix_length_and_dec() +bool Item_func_min_max::fix_length_and_dec() { uint unsigned_count= 0; int max_int_part=0; @@ -2836,6 +2847,7 @@ void Item_func_min_max::fix_length_and_dec() set_handler_by_field_type(MYSQL_TYPE_DOUBLE); break; } + return FALSE; } @@ -3086,10 +3098,10 @@ longlong Item_func_coercibility::val_int() } -void Item_func_locate::fix_length_and_dec() +bool Item_func_locate::fix_length_and_dec() { max_length= MY_INT32_NUM_DECIMAL_DIGITS; - agg_arg_charsets_for_comparison(cmp_collation, args, 2); + return agg_arg_charsets_for_comparison(cmp_collation, args, 2); } @@ -3206,14 +3218,15 @@ longlong Item_func_field::val_int() } -void Item_func_field::fix_length_and_dec() +bool Item_func_field::fix_length_and_dec() { maybe_null=0; max_length=3; cmp_type= args[0]->result_type(); for (uint i=1; i < arg_count ; i++) cmp_type= item_cmp_type(cmp_type, args[i]->result_type()); if (cmp_type == STRING_RESULT) - agg_arg_charsets_for_comparison(cmp_collation, args, arg_count); + return agg_arg_charsets_for_comparison(cmp_collation, args, arg_count); + return FALSE; } @@ -3260,7 +3273,7 @@ longlong Item_func_ord::val_int() /* Returns number of found type >= 1 or 0 if not found */ /* This optimizes searching in enums to bit testing! */ -void Item_func_find_in_set::fix_length_and_dec() +bool Item_func_find_in_set::fix_length_and_dec() { decimals=0; max_length=3; // 1-999 @@ -3282,7 +3295,7 @@ void Item_func_find_in_set::fix_length_and_dec() } } } - agg_arg_charsets_for_comparison(cmp_collation, args, 2); + return agg_arg_charsets_for_comparison(cmp_collation, args, 2); } static const char separator=','; @@ -3487,7 +3500,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, DBUG_RETURN(TRUE); } } - func->fix_length_and_dec(); + if (func->fix_length_and_dec()) + DBUG_RETURN(TRUE); initid.max_length=func->max_length; initid.maybe_null=func->maybe_null; initid.const_item=func->const_item_cache; @@ -3825,13 +3839,13 @@ String *Item_func_udf_decimal::val_str(String *str) /* Default max_length is max argument length */ -void Item_func_udf_str::fix_length_and_dec() +bool Item_func_udf_str::fix_length_and_dec() { DBUG_ENTER("Item_func_udf_str::fix_length_and_dec"); max_length=0; for (uint i = 0; i < arg_count; i++) set_if_bigger(max_length,args[i]->max_length); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } String *Item_func_udf_str::val_str(String *str) @@ -4718,7 +4732,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) } -void +bool Item_func_set_user_var::fix_length_and_dec() { maybe_null=args[0]->maybe_null; @@ -4732,6 +4746,7 @@ Item_func_set_user_var::fix_length_and_dec() args[0]->collation.collation); } unsigned_flag= args[0]->unsigned_flag; + return FALSE; } @@ -5570,7 +5585,7 @@ get_var_with_binlog(THD *thd, enum_sql_command sql_command, return 1; } -void Item_func_get_user_var::fix_length_and_dec() +bool Item_func_get_user_var::fix_length_and_dec() { THD *thd=current_thd; int error; @@ -5620,6 +5635,7 @@ void Item_func_get_user_var::fix_length_and_dec() set_handler_by_field_type(MYSQL_TYPE_LONG_BLOB); max_length= MAX_BLOB_WIDTH; } + return false; } @@ -5762,7 +5778,7 @@ void Item_func_get_system_var::update_null_value() } -void Item_func_get_system_var::fix_length_and_dec() +bool Item_func_get_system_var::fix_length_and_dec() { char *cptr; maybe_null= TRUE; @@ -5774,7 +5790,7 @@ void Item_func_get_system_var::fix_length_and_dec() { my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL"); - return; + return TRUE; } /* As there was no local variable, return the global value */ var_type= OPT_GLOBAL; @@ -5838,6 +5854,7 @@ void Item_func_get_system_var::fix_length_and_dec() my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); break; } + return FALSE; } @@ -6614,7 +6631,7 @@ bool Item_func_sp::is_expensive() @note called from Item::fix_fields. */ -void Item_func_sp::fix_length_and_dec() +bool Item_func_sp::fix_length_and_dec() { DBUG_ENTER("Item_func_sp::fix_length_and_dec"); @@ -6622,7 +6639,7 @@ void Item_func_sp::fix_length_and_dec() Type_std_attributes::set(sp_result_field); maybe_null= 1; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -6961,11 +6978,12 @@ my_decimal *Item_func_last_value::val_decimal(my_decimal *decimal_value) } -void Item_func_last_value::fix_length_and_dec() +bool Item_func_last_value::fix_length_and_dec() { last_value= args[arg_count -1]; Type_std_attributes::set(last_value); maybe_null= last_value->maybe_null; + return FALSE; } diff --git a/sql/item_func.h b/sql/item_func.h index 689bfb84034..0312b21328c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -391,8 +391,8 @@ class Item_real_func :public Item_func { DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); } enum Item_result result_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() - { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } + bool fix_length_and_dec() + { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); return FALSE; } }; @@ -569,7 +569,7 @@ class Item_func_num1: public Item_func_numhybrid public: Item_func_num1(THD *thd, Item *a): Item_func_numhybrid(thd, a) {} Item_func_num1(THD *thd, Item *a, Item *b): Item_func_numhybrid(thd, a, b) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); }; @@ -584,7 +584,7 @@ class Item_num_op :public Item_func_numhybrid { print_op(str, query_type); } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool need_parentheses_in_default() { return true; } }; @@ -611,7 +611,7 @@ class Item_int_func :public Item_func String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } - void fix_length_and_dec() {} + bool fix_length_and_dec() { return FALSE; } }; @@ -622,7 +622,7 @@ class Item_func_connection_id :public Item_int_func public: Item_func_connection_id(THD *thd): Item_int_func(thd) {} const char *func_name() const { return "connection_id"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool fix_fields(THD *thd, Item **ref); longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } bool check_vcol_func_processor(void *arg) @@ -648,7 +648,7 @@ class Item_func_signed :public Item_int_func null_value= args[0]->null_value; return value; } - void fix_length_and_dec() + bool fix_length_and_dec() { uint32 char_length= MY_MIN(args[0]->max_char_length(), MY_INT64_NUM_DECIMAL_DIGITS); @@ -659,6 +659,7 @@ class Item_func_signed :public Item_int_func */ set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1)); fix_char_length(char_length); + return FALSE; } virtual void print(String *str, enum_query_type query_type); uint decimal_precision() const { return args[0]->decimal_precision(); } @@ -705,7 +706,7 @@ class Item_decimal_typecast :public Item_func my_decimal *val_decimal(my_decimal*); enum Item_result result_type () const { return DECIMAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } - void fix_length_and_dec() {} + bool fix_length_and_dec() { return FALSE; } const char *func_name() const { return "decimal_typecast"; } virtual void print(String *str, enum_query_type query_type); bool need_parentheses_in_default() { return true; } @@ -725,7 +726,7 @@ class Item_double_typecast :public Item_real_func } double val_real(); enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() { maybe_null= 1; } + bool fix_length_and_dec() { maybe_null= 1; return FALSE; } const char *func_name() const { return "double_typecast"; } virtual void print(String *str, enum_query_type query_type); bool need_parentheses_in_default() { return true; } @@ -769,7 +770,7 @@ class Item_func_minus :public Item_func_additive_op longlong int_op(); double real_op(); my_decimal *decimal_op(my_decimal *); - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_minus>(thd, mem_root, this); } }; @@ -803,7 +804,7 @@ class Item_func_div :public Item_num_op my_decimal *decimal_op(my_decimal *); const char *func_name() const { return "/"; } enum precedence precedence() const { return MUL_PRECEDENCE; } - void fix_length_and_dec(); + bool fix_length_and_dec(); void result_precision(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_div>(thd, mem_root, this); } @@ -818,7 +819,7 @@ class Item_func_int_div :public Item_int_func longlong val_int(); const char *func_name() const { return "DIV"; } enum precedence precedence() const { return MUL_PRECEDENCE; } - void fix_length_and_dec(); + bool fix_length_and_dec(); void print(String *str, enum_query_type query_type) { print_op(str, query_type); @@ -842,7 +843,7 @@ class Item_func_mod :public Item_num_op const char *func_name() const { return "%"; } enum precedence precedence() const { return MUL_PRECEDENCE; } void result_precision(); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -865,7 +866,7 @@ class Item_func_neg :public Item_func_num1 str->append(func_name()); args[0]->print_parenthesised(str, query_type, precedence()); } - void fix_length_and_dec(); + bool fix_length_and_dec(); uint decimal_precision() const { return args[0]->decimal_precision(); } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -883,7 +884,7 @@ class Item_func_abs :public Item_func_num1 longlong int_op(); my_decimal *decimal_op(my_decimal *); const char *func_name() const { return "abs"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -897,10 +898,11 @@ class Item_dec_func :public Item_real_func public: Item_dec_func(THD *thd, Item *a): Item_real_func(thd, a) {} Item_dec_func(THD *thd, Item *a, Item *b): Item_real_func(thd, a, b) {} - void fix_length_and_dec() + bool fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); maybe_null=1; + return FALSE; } }; @@ -1058,7 +1060,7 @@ class Item_func_int_val :public Item_func_num1 { public: Item_func_int_val(THD *thd, Item *a): Item_func_num1(thd, a) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); }; @@ -1103,7 +1105,7 @@ class Item_func_round :public Item_func_num1 double real_op(); longlong int_op(); my_decimal *decimal_op(my_decimal *); - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_round>(thd, mem_root, this); } }; @@ -1155,8 +1157,8 @@ class Item_func_units :public Item_real_func Item_real_func(thd, a), name(name_arg), mul(mul_arg), add(add_arg) {} double val_real(); const char *func_name() const { return name; } - void fix_length_and_dec() - { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } + bool fix_length_and_dec() + { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_units>(thd, mem_root, this); } }; @@ -1186,7 +1188,7 @@ class Item_func_min_max :public Item_hybrid_func String *val_str(String *); my_decimal *val_decimal(my_decimal *); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); - void fix_length_and_dec(); + bool fix_length_and_dec(); }; class Item_func_min :public Item_func_min_max @@ -1229,13 +1231,14 @@ class Item_func_rollup_const :public Item_func bool const_item() const { return 0; } Item_result result_type() const { return args[0]->result_type(); } enum_field_types field_type() const { return args[0]->field_type(); } - void fix_length_and_dec() + bool fix_length_and_dec() { collation= args[0]->collation; max_length= args[0]->max_length; decimals=args[0]->decimals; /* The item could be a NULL constant. */ null_value= args[0]->is_null(); + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_rollup_const>(thd, mem_root, this); } @@ -1249,7 +1252,7 @@ class Item_func_length :public Item_int_func Item_func_length(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "length"; } - void fix_length_and_dec() { max_length=10; } + bool fix_length_and_dec() { max_length=10; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_length>(thd, mem_root, this); } }; @@ -1272,7 +1275,7 @@ class Item_func_char_length :public Item_int_func Item_func_char_length(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "char_length"; } - void fix_length_and_dec() { max_length=10; } + bool fix_length_and_dec() { max_length=10; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_char_length>(thd, mem_root, this); } }; @@ -1283,7 +1286,7 @@ class Item_func_coercibility :public Item_int_func Item_func_coercibility(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "coercibility"; } - void fix_length_and_dec() { max_length=10; maybe_null= 0; } + bool fix_length_and_dec() { max_length=10; maybe_null= 0; return FALSE; } bool eval_not_null_tables(void *) { not_null_tables_cache= 0; @@ -1305,7 +1308,7 @@ class Item_func_locate :public Item_int_func Item_func_locate(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} const char *func_name() const { return "locate"; } longlong val_int(); - void fix_length_and_dec(); + bool fix_length_and_dec(); virtual void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_locate>(thd, mem_root, this); } @@ -1321,7 +1324,7 @@ class Item_func_field :public Item_int_func Item_func_field(THD *thd, List<Item> &list): Item_int_func(thd, list) {} longlong val_int(); const char *func_name() const { return "field"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_field>(thd, mem_root, this); } }; @@ -1334,7 +1337,7 @@ class Item_func_ascii :public Item_int_func Item_func_ascii(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "ascii"; } - void fix_length_and_dec() { max_length=3; } + bool fix_length_and_dec() { max_length=3; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_ascii>(thd, mem_root, this); } }; @@ -1361,7 +1364,7 @@ class Item_func_find_in_set :public Item_int_func Item_int_func(thd, a, b), enum_value(0) {} longlong val_int(); const char *func_name() const { return "find_in_set"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_find_in_set>(thd, mem_root, this); } }; @@ -1373,7 +1376,7 @@ class Item_func_bit: public Item_int_func public: Item_func_bit(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} Item_func_bit(THD *thd, Item *a): Item_int_func(thd, a) {} - void fix_length_and_dec() { unsigned_flag= 1; } + bool fix_length_and_dec() { unsigned_flag= 1; return FALSE; } virtual inline void print(String *str, enum_query_type query_type) { @@ -1410,7 +1413,7 @@ class Item_func_bit_count :public Item_int_func Item_func_bit_count(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "bit_count"; } - void fix_length_and_dec() { max_length=2; } + bool fix_length_and_dec() { max_length=2; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_bit_count>(thd, mem_root, this); } }; @@ -1461,12 +1464,13 @@ class Item_func_last_insert_id :public Item_int_func Item_func_last_insert_id(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "last_insert_id"; } - void fix_length_and_dec() + bool fix_length_and_dec() { unsigned_flag= TRUE; if (arg_count) max_length= args[0]->max_length; unsigned_flag=1; + return FALSE; } bool fix_fields(THD *thd, Item **ref); bool check_vcol_func_processor(void *arg) @@ -1486,7 +1490,7 @@ class Item_func_benchmark :public Item_int_func {} longlong val_int(); const char *func_name() const { return "benchmark"; } - void fix_length_and_dec() { max_length=1; maybe_null=0; } + bool fix_length_and_dec() { max_length=1; maybe_null=0; return FALSE; } virtual void print(String *str, enum_query_type query_type); bool check_vcol_func_processor(void *arg) { @@ -1644,7 +1648,7 @@ class Item_func_udf_float :public Item_udf_func double val_real(); String *val_str(String *str); enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() { fix_num_length_and_dec(); } + bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_udf_float>(thd, mem_root, this); } }; @@ -1663,7 +1667,7 @@ class Item_func_udf_int :public Item_udf_func String *val_str(String *str); enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } - void fix_length_and_dec() { decimals= 0; max_length= 21; } + bool fix_length_and_dec() { decimals= 0; max_length= 21; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_udf_int>(thd, mem_root, this); } }; @@ -1682,7 +1686,7 @@ class Item_func_udf_decimal :public Item_udf_func String *val_str(String *str); enum Item_result result_type () const { return DECIMAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } - void fix_length_and_dec() { fix_num_length_and_dec(); } + bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_udf_decimal>(thd, mem_root, this); } }; @@ -1722,7 +1726,7 @@ class Item_func_udf_str :public Item_udf_func } enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return string_field_type(); } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_udf_str>(thd, mem_root, this); } }; @@ -1774,7 +1778,7 @@ class Item_func_udf_str :public Item_func double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; } longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() { maybe_null=1; max_length=0; } + bool fix_length_and_dec() { maybe_null=1; max_length=0; return FALSE; } }; #endif /* HAVE_DLOPEN */ @@ -1789,7 +1793,7 @@ class Item_func_get_lock :public Item_int_func Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_int_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "get_lock"; } - void fix_length_and_dec() { max_length=1; maybe_null=1;} + bool fix_length_and_dec() { max_length=1; maybe_null=1; return FALSE; } table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; @@ -1811,7 +1815,7 @@ class Item_func_release_lock :public Item_int_func Item_func_release_lock(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "release_lock"; } - void fix_length_and_dec() { max_length= 1; maybe_null= 1;} + bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; } table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; @@ -1839,7 +1843,7 @@ class Item_master_pos_wait :public Item_int_func Item_int_func(thd, a, b, c, d) {} longlong val_int(); const char *func_name() const { return "master_pos_wait"; } - void fix_length_and_dec() { max_length=21; maybe_null=1;} + bool fix_length_and_dec() { max_length=21; maybe_null=1; return FALSE; } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); @@ -1857,7 +1861,7 @@ class Item_master_gtid_wait :public Item_int_func Item_master_gtid_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "master_gtid_wait"; } - void fix_length_and_dec() { max_length=2; } + bool fix_length_and_dec() { max_length=2; return FALSE; } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); @@ -1948,7 +1952,7 @@ class Item_func_set_user_var :public Item_func_user_var void save_item_result(Item *item); bool update(); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); Field *create_field_for_create_select(TABLE *table) { return result_type() != STRING_RESULT ? @@ -1989,7 +1993,7 @@ class Item_func_get_user_var :public Item_func_user_var, longlong val_int(); my_decimal *val_decimal(my_decimal*); String *val_str(String* str); - void fix_length_and_dec(); + bool fix_length_and_dec(); virtual void print(String *str, enum_query_type query_type); /* We must always return variables as strings to guard against selects of type @@ -2071,7 +2075,7 @@ class Item_func_get_system_var :public Item_func size_t name_len_arg); enum Functype functype() const { return GSYSVAR_FUNC; } void update_null_value(); - void fix_length_and_dec(); + bool fix_length_and_dec(); void print(String *str, enum_query_type query_type); bool const_item() const { return true; } table_map used_tables() const { return 0; } @@ -2210,7 +2214,11 @@ class Item_func_is_free_lock :public Item_int_func Item_func_is_free_lock(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "is_free_lock"; } - void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;} + bool fix_length_and_dec() + { + decimals=0; max_length=1; maybe_null=1; + return FALSE; + } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); @@ -2226,7 +2234,11 @@ class Item_func_is_used_lock :public Item_int_func Item_func_is_used_lock(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "is_used_lock"; } - void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;} + bool fix_length_and_dec() + { + decimals=0; max_length=10; maybe_null=1; + return FALSE; + } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); @@ -2278,7 +2290,7 @@ class Item_func_row_count :public Item_int_func Item_func_row_count(THD *thd): Item_int_func(thd) {} longlong val_int(); const char *func_name() const { return "row_count"; } - void fix_length_and_dec() { decimals= 0; maybe_null=0; } + bool fix_length_and_dec() { decimals= 0; maybe_null=0; return FALSE; } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); @@ -2406,7 +2418,7 @@ class Item_func_sp :public Item_func virtual enum Functype functype() const { return FUNC_SP; } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(void); + bool fix_length_and_dec(void); bool is_expensive(); inline Field *get_sp_result_field() @@ -2442,7 +2454,7 @@ class Item_func_found_rows :public Item_int_func Item_func_found_rows(THD *thd): Item_int_func(thd) {} longlong val_int(); const char *func_name() const { return "found_rows"; } - void fix_length_and_dec() { decimals= 0; maybe_null=0; } + bool fix_length_and_dec() { decimals= 0; maybe_null=0; return FALSE; } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE); @@ -2461,8 +2473,8 @@ class Item_func_uuid_short :public Item_int_func const char *func_name() const { return "uuid_short"; } longlong val_int(); bool const_item() const { return false; } - void fix_length_and_dec() - { max_length= 21; unsigned_flag=1; } + bool fix_length_and_dec() + { max_length= 21; unsigned_flag=1; return FALSE; } table_map used_tables() const { return RAND_TABLE_BIT; } bool check_vcol_func_processor(void *arg) { @@ -2483,7 +2495,7 @@ class Item_func_last_value :public Item_func longlong val_int(); String *val_str(String *); my_decimal *val_decimal(my_decimal *); - void fix_length_and_dec(); + bool fix_length_and_dec(); enum Item_result result_type () const { return last_value->result_type(); } const char *func_name() const { return "last_value"; } bool eval_not_null_tables(void *) diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 3119f5a577b..246be438e36 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -49,12 +49,13 @@ Field *Item_geometry_func::create_field_for_create_select(TABLE *t_arg) return result; } -void Item_geometry_func::fix_length_and_dec() +bool Item_geometry_func::fix_length_and_dec() { collation.set(&my_charset_bin); decimals=0; max_length= (uint32) 4294967295U; maybe_null= 1; + return FALSE; } @@ -223,11 +224,12 @@ String *Item_func_as_wkt::val_str_ascii(String *str) } -void Item_func_as_wkt::fix_length_and_dec() +bool Item_func_as_wkt::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); max_length=MAX_BLOB_WIDTH; maybe_null= 1; + return FALSE; } @@ -249,11 +251,12 @@ String *Item_func_as_wkb::val_str(String *str) } -void Item_func_as_geojson::fix_length_and_dec() +bool Item_func_as_geojson::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); max_length=MAX_BLOB_WIDTH; maybe_null= 1; + return FALSE; } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 199bc1f47de..acc94183d47 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -38,7 +38,7 @@ class Item_geometry_func: public Item_str_func Item_geometry_func(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } Field *create_field_for_create_select(TABLE *table); }; @@ -90,7 +90,7 @@ class Item_func_as_wkt: public Item_str_ascii_func Item_func_as_wkt(THD *thd, Item *a): Item_str_ascii_func(thd, a) {} const char *func_name() const { return "st_astext"; } String *val_str_ascii(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_as_wkt>(thd, mem_root, this); } }; @@ -116,7 +116,7 @@ class Item_func_as_geojson: public Item_str_ascii_func Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt): Item_str_ascii_func(thd, js, max_dec_digits, opt) {} const char *func_name() const { return "st_asgeojson"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str_ascii(String *); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_as_geojson>(thd, mem_root, this); } @@ -129,11 +129,12 @@ class Item_func_geometry_type: public Item_str_ascii_func Item_func_geometry_type(THD *thd, Item *a): Item_str_ascii_func(thd, a) {} String *val_str_ascii(String *); const char *func_name() const { return "st_geometrytype"; } - void fix_length_and_dec() + bool fix_length_and_dec() { // "GeometryCollection" is the longest fix_length_and_charset(20, default_charset()); maybe_null= 1; + return FALSE; }; Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_geometry_type>(thd, mem_root, this); } @@ -308,9 +309,10 @@ class Item_func_spatial_collection: public Item_geometry_func item_type=it; } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { - Item_geometry_func::fix_length_and_dec(); + if (Item_geometry_func::fix_length_and_dec()) + return TRUE; for (unsigned int i= 0; i < arg_count; ++i) { if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) @@ -320,8 +322,10 @@ class Item_func_spatial_collection: public Item_geometry_func str.append('\0'); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric", str.ptr()); + return TRUE; } } + return FALSE; } const char *func_name() const { return "geometrycollection"; } @@ -510,7 +514,7 @@ class Item_func_isempty: public Item_bool_func Item_func_isempty(THD *thd, Item *a): Item_bool_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_isempty"; } - void fix_length_and_dec() { maybe_null= 1; } + bool fix_length_and_dec() { maybe_null= 1; return FALSE; } bool need_parentheses_in_default() { return false; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_isempty>(thd, mem_root, this); } @@ -526,7 +530,7 @@ class Item_func_issimple: public Item_int_func Item_func_issimple(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_issimple"; } - void fix_length_and_dec() { decimals=0; max_length=2; } + bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; } uint decimal_precision() const { return 1; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_issimple>(thd, mem_root, this); } @@ -538,7 +542,7 @@ class Item_func_isclosed: public Item_int_func Item_func_isclosed(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_isclosed"; } - void fix_length_and_dec() { decimals=0; max_length=2; } + bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; } uint decimal_precision() const { return 1; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_isclosed>(thd, mem_root, this); } @@ -561,7 +565,7 @@ class Item_func_dimension: public Item_int_func Item_func_dimension(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_dimension"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_dimension>(thd, mem_root, this); } }; @@ -573,10 +577,12 @@ class Item_func_x: public Item_real_func Item_func_x(THD *thd, Item *a): Item_real_func(thd, a) {} double val_real(); const char *func_name() const { return "st_x"; } - void fix_length_and_dec() - { - Item_real_func::fix_length_and_dec(); - maybe_null= 1; + bool fix_length_and_dec() + { + if (Item_real_func::fix_length_and_dec()) + return TRUE; + maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_x>(thd, mem_root, this); } @@ -590,10 +596,12 @@ class Item_func_y: public Item_real_func Item_func_y(THD *thd, Item *a): Item_real_func(thd, a) {} double val_real(); const char *func_name() const { return "st_y"; } - void fix_length_and_dec() - { - Item_real_func::fix_length_and_dec(); - maybe_null= 1; + bool fix_length_and_dec() + { + if (Item_real_func::fix_length_and_dec()) + return TRUE; + maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_y>(thd, mem_root, this); } @@ -607,7 +615,7 @@ class Item_func_numgeometries: public Item_int_func Item_func_numgeometries(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_numgeometries"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_numgeometries>(thd, mem_root, this); } }; @@ -620,7 +628,7 @@ class Item_func_numinteriorring: public Item_int_func Item_func_numinteriorring(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_numinteriorrings"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_numinteriorring>(thd, mem_root, this); } }; @@ -633,7 +641,7 @@ class Item_func_numpoints: public Item_int_func Item_func_numpoints(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "st_numpoints"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_numpoints>(thd, mem_root, this); } }; @@ -646,10 +654,12 @@ class Item_func_area: public Item_real_func Item_func_area(THD *thd, Item *a): Item_real_func(thd, a) {} double val_real(); const char *func_name() const { return "st_area"; } - void fix_length_and_dec() - { - Item_real_func::fix_length_and_dec(); - maybe_null= 1; + bool fix_length_and_dec() + { + if (Item_real_func::fix_length_and_dec()) + return TRUE; + maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_area>(thd, mem_root, this); } @@ -663,10 +673,12 @@ class Item_func_glength: public Item_real_func Item_func_glength(THD *thd, Item *a): Item_real_func(thd, a) {} double val_real(); const char *func_name() const { return "st_length"; } - void fix_length_and_dec() - { - Item_real_func::fix_length_and_dec(); - maybe_null= 1; + bool fix_length_and_dec() + { + if (Item_real_func::fix_length_and_dec()) + return TRUE; + maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_glength>(thd, mem_root, this); } @@ -680,7 +692,7 @@ class Item_func_srid: public Item_int_func Item_func_srid(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "srid"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_srid>(thd, mem_root, this); } }; diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h index f19749df0af..670dce3da9f 100644 --- a/sql/item_inetfunc.h +++ b/sql/item_inetfunc.h @@ -30,12 +30,13 @@ class Item_func_inet_aton : public Item_int_func Item_func_inet_aton(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "inet_aton"; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals= 0; max_length= 21; maybe_null= 1; unsigned_flag= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_inet_aton>(thd, mem_root, this); } @@ -53,11 +54,12 @@ class Item_func_inet_ntoa : public Item_str_func { } String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals= 0; fix_length_and_charset(3 * 8 + 7, default_charset()); maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_inet_ntoa>(thd, mem_root, this); } @@ -122,11 +124,12 @@ class Item_func_inet6_aton : public Item_func_inet_str_base virtual const char *func_name() const { return "inet6_aton"; } - virtual void fix_length_and_dec() + virtual bool fix_length_and_dec() { decimals= 0; fix_length_and_charset(16, &my_charset_bin); maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_inet6_aton>(thd, mem_root, this); } @@ -151,7 +154,7 @@ class Item_func_inet6_ntoa : public Item_func_inet_str_base virtual const char *func_name() const { return "inet6_ntoa"; } - virtual void fix_length_and_dec() + virtual bool fix_length_and_dec() { decimals= 0; @@ -161,6 +164,7 @@ class Item_func_inet6_ntoa : public Item_func_inet_str_base fix_length_and_charset(8 * 4 + 7, default_charset()); maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_inet6_ntoa>(thd, mem_root, this); } diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 794831ae1a5..72aeac5b930 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -388,11 +388,13 @@ longlong Item_func_json_valid::val_int() } -void Item_func_json_exists::fix_length_and_dec() +bool Item_func_json_exists::fix_length_and_dec() { - Item_int_func::fix_length_and_dec(); + if (Item_int_func::fix_length_and_dec()) + return TRUE; maybe_null= 1; path.set_constant_flag(args[1]->const_item()); + return FALSE; } @@ -439,12 +441,13 @@ longlong Item_func_json_exists::val_int() } -void Item_func_json_value::fix_length_and_dec() +bool Item_func_json_value::fix_length_and_dec() { collation.set(args[0]->collation); max_length= args[0]->max_length; path.set_constant_flag(args[1]->const_item()); maybe_null= 1; + return FALSE; } @@ -546,7 +549,7 @@ bool Item_func_json_query::check_and_get_value(json_engine_t *je, String *res, } -void Item_func_json_quote::fix_length_and_dec() +bool Item_func_json_quote::fix_length_and_dec() { collation.set(&my_charset_utf8mb4_bin); /* @@ -554,6 +557,7 @@ void Item_func_json_quote::fix_length_and_dec() of the argument turn into '\uXXXX\uXXXX', which is 12. */ max_length= args[0]->max_length * 12 + 2; + return FALSE; } @@ -581,12 +585,13 @@ String *Item_func_json_quote::val_str(String *str) } -void Item_func_json_unquote::fix_length_and_dec() +bool Item_func_json_unquote::fix_length_and_dec() { collation.set(&my_charset_utf8_general_ci, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); max_length= args[0]->max_length; maybe_null= 1; + return FALSE; } @@ -702,13 +707,14 @@ void Item_json_str_multipath::cleanup() } -void Item_func_json_extract::fix_length_and_dec() +bool Item_func_json_extract::fix_length_and_dec() { collation.set(args[0]->collation); max_length= args[0]->max_length * (arg_count - 1); mark_constant_paths(paths, args+1, arg_count-1); maybe_null= 1; + return FALSE; } @@ -937,14 +943,14 @@ double Item_func_json_extract::val_real() } -void Item_func_json_contains::fix_length_and_dec() +bool Item_func_json_contains::fix_length_and_dec() { a2_constant= args[1]->const_item(); a2_parsed= FALSE; maybe_null= 1; if (arg_count > 2) path.set_constant_flag(args[2]->const_item()); - Item_int_func::fix_length_and_dec(); + return Item_int_func::fix_length_and_dec(); } @@ -1190,13 +1196,13 @@ bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref) } -void Item_func_json_contains_path::fix_length_and_dec() +bool Item_func_json_contains_path::fix_length_and_dec() { ooa_constant= args[1]->const_item(); ooa_parsed= FALSE; maybe_null= 1; mark_constant_paths(paths, args+2, arg_count-2); - Item_int_func::fix_length_and_dec(); + return Item_int_func::fix_length_and_dec(); } @@ -1454,7 +1460,7 @@ static int append_json_keyname(String *str, Item *item, String *tmp_val) } -void Item_func_json_array::fix_length_and_dec() +bool Item_func_json_array::fix_length_and_dec() { ulonglong char_length= 2; uint n_arg; @@ -1467,17 +1473,18 @@ void Item_func_json_array::fix_length_and_dec() DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); tmp_val.set_charset(&my_charset_utf8_general_ci); max_length= 2; - return; + return FALSE; } if (agg_arg_charsets_for_string_result(collation, args, arg_count)) - return; + return TRUE; for (n_arg=0 ; n_arg < arg_count ; n_arg++) char_length+= args[n_arg]->max_char_length() + 4; fix_char_length_ulonglong(char_length); tmp_val.set_charset(collation.collation); + return FALSE; } @@ -1521,7 +1528,7 @@ String *Item_func_json_array::val_str(String *str) } -void Item_func_json_array_append::fix_length_and_dec() +bool Item_func_json_array_append::fix_length_and_dec() { uint n_arg; ulonglong char_length; @@ -1536,6 +1543,7 @@ void Item_func_json_array_append::fix_length_and_dec() } fix_char_length_ulonglong(char_length); + return FALSE; } @@ -2122,11 +2130,12 @@ String *Item_func_json_merge::val_str(String *str) } -void Item_func_json_length::fix_length_and_dec() +bool Item_func_json_length::fix_length_and_dec() { if (arg_count > 1) path.set_constant_flag(args[1]->const_item()); maybe_null= 1; + return FALSE; } @@ -2266,11 +2275,12 @@ longlong Item_func_json_depth::val_int() } -void Item_func_json_type::fix_length_and_dec() +bool Item_func_json_type::fix_length_and_dec() { collation.set(&my_charset_utf8_general_ci); max_length= 12; maybe_null= 1; + return FALSE; } @@ -2323,7 +2333,7 @@ String *Item_func_json_type::val_str(String *str) } -void Item_func_json_insert::fix_length_and_dec() +bool Item_func_json_insert::fix_length_and_dec() { uint n_arg; ulonglong char_length; @@ -2339,6 +2349,7 @@ void Item_func_json_insert::fix_length_and_dec() fix_char_length_ulonglong(char_length); maybe_null= 1; + return FALSE; } @@ -2583,13 +2594,14 @@ String *Item_func_json_insert::val_str(String *str) } -void Item_func_json_remove::fix_length_and_dec() +bool Item_func_json_remove::fix_length_and_dec() { collation.set(args[0]->collation); max_length= args[0]->max_length; mark_constant_paths(paths, args+1, arg_count-1); maybe_null= 1; + return FALSE; } @@ -2769,13 +2781,14 @@ String *Item_func_json_remove::val_str(String *str) } -void Item_func_json_keys::fix_length_and_dec() +bool Item_func_json_keys::fix_length_and_dec() { collation.set(args[0]->collation); max_length= args[0]->max_length; maybe_null= 1; if (arg_count > 1) path.set_constant_flag(args[1]->const_item()); + return FALSE; } @@ -2936,7 +2949,7 @@ bool Item_func_json_search::fix_fields(THD *thd, Item **ref) static const uint SQR_MAX_BLOB_WIDTH= (uint) sqrt(MAX_BLOB_WIDTH); -void Item_func_json_search::fix_length_and_dec() +bool Item_func_json_search::fix_length_and_dec() { collation.set(args[0]->collation); @@ -2958,6 +2971,7 @@ void Item_func_json_search::fix_length_and_dec() if (arg_count > 4) mark_constant_paths(paths, args+4, arg_count-4); maybe_null= 1; + return FALSE; } @@ -3135,11 +3149,12 @@ const char *Item_func_json_format::func_name() const } -void Item_func_json_format::fix_length_and_dec() +bool Item_func_json_format::fix_length_and_dec() { decimals= 0; max_length= args[0]->max_length; maybe_null= 1; + return FALSE; } diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 927b60015b8..f331ee3b582 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -49,10 +49,12 @@ class Item_func_json_valid: public Item_int_func Item_func_json_valid(THD *thd, Item *json) : Item_int_func(thd, json) {} longlong val_int(); const char *func_name() const { return "json_valid"; } - void fix_length_and_dec() + bool fix_length_and_dec() { - Item_int_func::fix_length_and_dec(); + if (Item_int_func::fix_length_and_dec()) + return TRUE; maybe_null= 1; + return FALSE; } bool is_bool_type() { return true; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -71,7 +73,7 @@ class Item_func_json_exists: public Item_int_func Item_int_func(thd, js, i_path) {} const char *func_name() const { return "json_exists"; } bool is_bool_type() { return true; } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_exists>(thd, mem_root, this); } longlong val_int(); @@ -88,7 +90,7 @@ class Item_func_json_value: public Item_str_func Item_func_json_value(THD *thd, Item *js, Item *i_path): Item_str_func(thd, js, i_path) {} const char *func_name() const { return "json_value"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); virtual bool check_and_get_value(json_engine_t *je, String *res, int *error); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -117,7 +119,7 @@ class Item_func_json_quote: public Item_str_func public: Item_func_json_quote(THD *thd, Item *s): Item_str_func(thd, s) {} const char *func_name() const { return "json_quote"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_quote>(thd, mem_root, this); } @@ -132,7 +134,7 @@ class Item_func_json_unquote: public Item_str_func public: Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {} const char *func_name() const { return "json_unquote"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_unquote>(thd, mem_root, this); } @@ -165,7 +167,7 @@ class Item_func_json_extract: public Item_json_str_multipath Item_json_str_multipath(thd, list) {} const char *func_name() const { return "json_extract"; } enum Functype functype() const { return JSON_EXTRACT_FUNC; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); longlong val_int(); double val_real(); @@ -187,7 +189,7 @@ class Item_func_json_contains: public Item_int_func Item_func_json_contains(THD *thd, List<Item> &list): Item_int_func(thd, list) {} const char *func_name() const { return "json_contains"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); longlong val_int(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_contains>(thd, mem_root, this); } @@ -209,7 +211,7 @@ class Item_func_json_contains_path: public Item_int_func Item_int_func(thd, list), tmp_paths(0) {} const char *func_name() const { return "json_contains_path"; } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); void cleanup(); longlong val_int(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -229,7 +231,7 @@ class Item_func_json_array: public Item_str_func Item_str_func(thd, list) {} String *val_str(String *); bool is_json_type() { return true; } - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "json_array"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_array>(thd, mem_root, this); } @@ -244,7 +246,7 @@ class Item_func_json_array_append: public Item_json_str_multipath public: Item_func_json_array_append(THD *thd, List<Item> &list): Item_json_str_multipath(thd, list) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); uint get_n_paths() const { return arg_count/2; } const char *func_name() const { return "json_array_append"; } @@ -305,7 +307,7 @@ class Item_func_json_length: public Item_int_func Item_func_json_length(THD *thd, List<Item> &list): Item_int_func(thd, list) {} const char *func_name() const { return "json_length"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); longlong val_int(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_length>(thd, mem_root, this); } @@ -332,7 +334,7 @@ class Item_func_json_type: public Item_str_func public: Item_func_json_type(THD *thd, Item *js): Item_str_func(thd, js) {} const char *func_name() const { return "json_type"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_type>(thd, mem_root, this); } @@ -349,7 +351,7 @@ class Item_func_json_insert: public Item_json_str_multipath Item_func_json_insert(bool i_mode, bool r_mode, THD *thd, List<Item> &list): Item_json_str_multipath(thd, list), mode_insert(i_mode), mode_replace(r_mode) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); uint get_n_paths() const { return arg_count/2; } const char *func_name() const @@ -369,7 +371,7 @@ class Item_func_json_remove: public Item_json_str_multipath public: Item_func_json_remove(THD *thd, List<Item> &list): Item_json_str_multipath(thd, list) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); uint get_n_paths() const { return arg_count - 1; } const char *func_name() const { return "json_remove"; } @@ -388,7 +390,7 @@ class Item_func_json_keys: public Item_str_func Item_func_json_keys(THD *thd, List<Item> &list): Item_str_func(thd, list) {} const char *func_name() const { return "json_keys"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_json_keys>(thd, mem_root, this); } @@ -412,7 +414,7 @@ class Item_func_json_search: public Item_json_str_multipath Item_json_str_multipath(thd, list) {} const char *func_name() const { return "json_search"; } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *); uint get_n_paths() const { return arg_count > 4 ? arg_count - 4 : 0; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -440,7 +442,7 @@ class Item_func_json_format: public Item_str_func Item_str_func(thd, list), fmt(DETAILED) {} const char *func_name() const; - void fix_length_and_dec(); + bool fix_length_and_dec(); String *val_str(String *str); String *val_json(String *str); bool is_json_type() { return true; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3d543c8c390..87c766340c7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -188,10 +188,11 @@ String *Item_func_sha::val_str_ascii(String *str) return 0; } -void Item_func_sha::fix_length_and_dec() +bool Item_func_sha::fix_length_and_dec() { // size of hex representation of hash fix_length_and_charset(MY_SHA1_HASH_SIZE * 2, default_charset()); + return FALSE; } String *Item_func_sha2::val_str_ascii(String *str) @@ -267,7 +268,7 @@ String *Item_func_sha2::val_str_ascii(String *str) } -void Item_func_sha2::fix_length_and_dec() +bool Item_func_sha2::fix_length_and_dec() { maybe_null= 1; max_length = 0; @@ -292,6 +293,7 @@ void Item_func_sha2::fix_length_and_dec() ER_THD(thd, ER_WRONG_PARAMETERS_TO_NATIVE_FCT), "sha2"); } + return FALSE; } /* Implementation of AES encryption routines */ @@ -344,23 +346,25 @@ String *Item_aes_crypt::val_str(String *str2) return 0; } -void Item_func_aes_encrypt::fix_length_and_dec() +bool Item_func_aes_encrypt::fix_length_and_dec() { max_length=my_aes_get_size(MY_AES_ECB, args[0]->max_length); what= ENCRYPTION_FLAG_ENCRYPT; + return FALSE; } -void Item_func_aes_decrypt::fix_length_and_dec() +bool Item_func_aes_decrypt::fix_length_and_dec() { max_length=args[0]->max_length; maybe_null= 1; what= ENCRYPTION_FLAG_DECRYPT; + return FALSE; } -void Item_func_to_base64::fix_length_and_dec() +bool Item_func_to_base64::fix_length_and_dec() { maybe_null= args[0]->maybe_null; collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); @@ -375,6 +379,7 @@ void Item_func_to_base64::fix_length_and_dec() DBUG_ASSERT(length > 0); fix_char_length_ulonglong((ulonglong) length - 1); } + return FALSE; } @@ -410,7 +415,7 @@ String *Item_func_to_base64::val_str_ascii(String *str) } -void Item_func_from_base64::fix_length_and_dec() +bool Item_func_from_base64::fix_length_and_dec() { if (args[0]->max_length > (uint) my_base64_decode_max_arg_length()) { @@ -422,6 +427,7 @@ void Item_func_from_base64::fix_length_and_dec() fix_char_length_ulonglong((ulonglong) length); } maybe_null= 1; // Can be NULL, e.g. in case of badly formed input string + return FALSE; } @@ -630,17 +636,18 @@ String *Item_func_concat::val_str(String *str) } -void Item_func_concat::fix_length_and_dec() +bool Item_func_concat::fix_length_and_dec() { ulonglong char_length= 0; if (agg_arg_charsets_for_string_result(collation, args, arg_count)) - return; + return TRUE; for (uint i=0 ; i < arg_count ; i++) char_length+= args[i]->max_char_length(); fix_char_length_ulonglong(char_length); + return FALSE; } /** @@ -992,12 +999,12 @@ String *Item_func_concat_ws::val_str(String *str) } -void Item_func_concat_ws::fix_length_and_dec() +bool Item_func_concat_ws::fix_length_and_dec() { ulonglong char_length; if (agg_arg_charsets_for_string_result(collation, args, arg_count)) - return; + return TRUE; /* arg_count cannot be less than 2, @@ -1009,6 +1016,7 @@ void Item_func_concat_ws::fix_length_and_dec() char_length+= args[i]->max_char_length(); fix_char_length_ulonglong(char_length); + return FALSE; } @@ -1062,11 +1070,12 @@ String *Item_func_reverse::val_str(String *str) } -void Item_func_reverse::fix_length_and_dec() +bool Item_func_reverse::fix_length_and_dec() { agg_arg_charsets_for_string_result(collation, args, 1); DBUG_ASSERT(collation.collation != NULL); fix_char_length(args[0]->max_char_length()); + return FALSE; } /** @@ -1208,7 +1217,7 @@ String *Item_func_replace::val_str(String *str) } -void Item_func_replace::fix_length_and_dec() +bool Item_func_replace::fix_length_and_dec() { ulonglong char_length= (ulonglong) args[0]->max_char_length(); int diff=(int) (args[2]->max_char_length() - args[1]->max_char_length()); @@ -1219,8 +1228,9 @@ void Item_func_replace::fix_length_and_dec() } if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3)) - return; + return TRUE; fix_char_length_ulonglong(char_length); + return FALSE; } @@ -1232,13 +1242,14 @@ bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref) } -void Item_func_regexp_replace::fix_length_and_dec() +bool Item_func_regexp_replace::fix_length_and_dec() { if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3)) - return; + return TRUE; max_length= MAX_BLOB_WIDTH; re.init(collation.collation, 0); re.fix_owner(this, args[0], args[1]); + return FALSE; } @@ -1374,13 +1385,14 @@ bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref) } -void Item_func_regexp_substr::fix_length_and_dec() +bool Item_func_regexp_substr::fix_length_and_dec() { if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2)) - return; + return TRUE; fix_char_length(args[0]->max_char_length()); re.init(collation.collation, 0); re.fix_owner(this, args[0], args[1]); + return FALSE; } @@ -1488,16 +1500,17 @@ String *Item_func_insert::val_str(String *str) } -void Item_func_insert::fix_length_and_dec() +bool Item_func_insert::fix_length_and_dec() { ulonglong char_length; // Handle character set for args[0] and args[3]. if (agg_arg_charsets_for_string_result(collation, args, 2, 3)) - return; + return TRUE; char_length= ((ulonglong) args[0]->max_char_length() + (ulonglong) args[3]->max_char_length()); fix_char_length_ulonglong(char_length); + return FALSE; } @@ -1534,22 +1547,26 @@ String *Item_str_conv::val_str(String *str) } -void Item_func_lcase::fix_length_and_dec() +bool Item_func_lcase::fix_length_and_dec() { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); multiply= collation.collation->casedn_multiply; converter= collation.collation->cset->casedn; fix_char_length_ulonglong((ulonglong) args[0]->max_char_length() * multiply); + return FALSE; } -void Item_func_ucase::fix_length_and_dec() +bool Item_func_ucase::fix_length_and_dec() { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); multiply= collation.collation->caseup_multiply; converter= collation.collation->cset->caseup; fix_char_length_ulonglong((ulonglong) args[0]->max_char_length() * multiply); + return FALSE; } @@ -1592,11 +1609,13 @@ void Item_str_func::left_right_max_length() } -void Item_func_left::fix_length_and_dec() +bool Item_func_left::fix_length_and_dec() { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); left_right_max_length(); + return FALSE; } @@ -1626,11 +1645,13 @@ String *Item_func_right::val_str(String *str) } -void Item_func_right::fix_length_and_dec() +bool Item_func_right::fix_length_and_dec() { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); left_right_max_length(); + return FALSE; } @@ -1681,11 +1702,12 @@ String *Item_func_substr::val_str(String *str) } -void Item_func_substr::fix_length_and_dec() +bool Item_func_substr::fix_length_and_dec() { max_length=args[0]->max_length; - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); if (args[1]->const_item()) { @@ -1706,14 +1728,16 @@ void Item_func_substr::fix_length_and_dec() set_if_smaller(max_length,(uint) length); } max_length*= collation.collation->mbmaxlen; + return FALSE; } -void Item_func_substr_index::fix_length_and_dec() -{ +bool Item_func_substr_index::fix_length_and_dec() +{ if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2)) - return; + return TRUE; fix_char_length(args[0]->max_char_length()); + return FALSE; } @@ -2037,11 +2061,12 @@ String *Item_func_trim::val_str(String *str) return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr)); } -void Item_func_trim::fix_length_and_dec() +bool Item_func_trim::fix_length_and_dec() { if (arg_count == 1) { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); remove.set_charset(collation.collation); remove.set_ascii(" ",1); @@ -2052,9 +2077,10 @@ void Item_func_trim::fix_length_and_dec() // Note that we pass args[1] as the first item, and args[0] as the second. if (agg_arg_charsets_for_string_result_with_comparison(collation, &args[1], 2, -1)) - return; + return TRUE; } fix_char_length(args[0]->max_char_length()); + return FALSE; } void Item_func_trim::print(String *str, enum_query_type query_type) @@ -2194,7 +2220,7 @@ bool Item_func_encode::seed() return FALSE; } -void Item_func_encode::fix_length_and_dec() +bool Item_func_encode::fix_length_and_dec() { max_length=args[0]->max_length; maybe_null=args[0]->maybe_null || args[1]->maybe_null; @@ -2202,6 +2228,7 @@ void Item_func_encode::fix_length_and_dec() /* Precompute the seed state if the item is constant. */ seeded= args[1]->const_item() && (args[1]->result_type() == STRING_RESULT) && !seed(); + return FALSE; } String *Item_func_encode::val_str(String *str) @@ -2347,13 +2374,14 @@ bool Item_func_current_role::fix_fields(THD *thd, Item **ref) return 0; } -void Item_func_soundex::fix_length_and_dec() +bool Item_func_soundex::fix_length_and_dec() { uint32 char_length= args[0]->max_char_length(); agg_arg_charsets_for_string_result(collation, args, 1); DBUG_ASSERT(collation.collation != NULL); set_if_bigger(char_length, 4); fix_char_length(char_length); + return FALSE; } @@ -2529,7 +2557,7 @@ MY_LOCALE *Item_func_format::get_locale(Item *item) return lc; } -void Item_func_format::fix_length_and_dec() +bool Item_func_format::fix_length_and_dec() { uint32 char_length= args[0]->max_char_length(); uint32 max_sep_count= (char_length / 3) + (decimals ? 1 : 0) + /*sign*/1; @@ -2539,6 +2567,7 @@ void Item_func_format::fix_length_and_dec() locale= args[2]->basic_const_item() ? get_locale(args[2]) : NULL; else locale= &my_locale_en_US; /* Two arguments */ + return FALSE; } @@ -2652,13 +2681,13 @@ String *Item_func_format::val_str_ascii(String *str) } -void Item_func_elt::fix_length_and_dec() +bool Item_func_elt::fix_length_and_dec() { uint32 char_length= 0; decimals=0; if (agg_arg_charsets_for_string_result(collation, args + 1, arg_count - 1)) - return; + return TRUE; for (uint i= 1 ; i < arg_count ; i++) { @@ -2667,6 +2696,7 @@ void Item_func_elt::fix_length_and_dec() } fix_char_length(char_length); maybe_null=1; // NULL if wrong first arg + return FALSE; } @@ -2713,16 +2743,17 @@ String *Item_func_elt::val_str(String *str) } -void Item_func_make_set::fix_length_and_dec() +bool Item_func_make_set::fix_length_and_dec() { uint32 char_length= arg_count - 2; /* Separators */ if (agg_arg_charsets_for_string_result(collation, args + 1, arg_count - 1)) - return; + return TRUE; for (uint i=1 ; i < arg_count ; i++) char_length+= args[i]->max_char_length(); fix_char_length(char_length); + return FALSE; } @@ -2853,9 +2884,10 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value, } -void Item_func_repeat::fix_length_and_dec() +bool Item_func_repeat::fix_length_and_dec() { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); if (args[1]->const_item()) { @@ -2877,6 +2909,7 @@ void Item_func_repeat::fix_length_and_dec() max_length= MAX_BLOB_WIDTH; maybe_null= 1; } + return FALSE; } /** @@ -2938,7 +2971,7 @@ String *Item_func_repeat::val_str(String *str) } -void Item_func_space::fix_length_and_dec() +bool Item_func_space::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); if (args[0]->const_item()) @@ -2954,12 +2987,13 @@ void Item_func_space::fix_length_and_dec() if (count > INT_MAX32) count= INT_MAX32; fix_char_length_ulonglong(count); - return; + return FALSE; } end: max_length= MAX_BLOB_WIDTH; maybe_null= 1; + return FALSE; } @@ -3009,11 +3043,12 @@ String *Item_func_space::val_str(String *str) } -void Item_func_binlog_gtid_pos::fix_length_and_dec() +bool Item_func_binlog_gtid_pos::fix_length_and_dec() { collation.set(system_charset_info); max_length= MAX_BLOB_WIDTH; maybe_null= 1; + return FALSE; } @@ -3049,11 +3084,11 @@ String *Item_func_binlog_gtid_pos::val_str(String *str) } -void Item_func_rpad::fix_length_and_dec() +bool Item_func_rpad::fix_length_and_dec() { // Handle character set for args[0] and args[2]. if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2)) - return; + return TRUE; if (args[1]->const_item()) { ulonglong char_length= (ulonglong) args[1]->val_int(); @@ -3071,6 +3106,7 @@ void Item_func_rpad::fix_length_and_dec() max_length= MAX_BLOB_WIDTH; maybe_null= 1; } + return FALSE; } @@ -3157,12 +3193,12 @@ String *Item_func_rpad::val_str(String *str) } -void Item_func_lpad::fix_length_and_dec() +bool Item_func_lpad::fix_length_and_dec() { // Handle character set for args[0] and args[2]. if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2)) - return; - + return TRUE; + if (args[1]->const_item()) { ulonglong char_length= (ulonglong) args[1]->val_int(); @@ -3180,6 +3216,7 @@ void Item_func_lpad::fix_length_and_dec() max_length= MAX_BLOB_WIDTH; maybe_null= 1; } + return FALSE; } @@ -3329,10 +3366,11 @@ String *Item_func_conv_charset::val_str(String *str) 0 : str; } -void Item_func_conv_charset::fix_length_and_dec() +bool Item_func_conv_charset::fix_length_and_dec() { DBUG_ASSERT(collation.derivation == DERIVATION_IMPLICIT); fix_char_length(args[0]->max_char_length()); + return FALSE; } void Item_func_conv_charset::print(String *str, enum_query_type query_type) @@ -3354,7 +3392,7 @@ String *Item_func_set_collation::val_str(String *str) return str; } -void Item_func_set_collation::fix_length_and_dec() +bool Item_func_set_collation::fix_length_and_dec() { CHARSET_INFO *set_collation; const char *colname; @@ -3365,8 +3403,8 @@ void Item_func_set_collation::fix_length_and_dec() MY_CS_BINSORT,MYF(0)); else { - if (!(set_collation= mysqld_collation_get_by_name(colname))) - return; + if (!(set_collation= mysqld_collation_get_by_name(colname))) + return TRUE; } if (!set_collation || @@ -3374,11 +3412,12 @@ void Item_func_set_collation::fix_length_and_dec() { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), colname, args[0]->collation.collation->csname); - return; + return TRUE; } collation.set(set_collation, DERIVATION_EXPLICIT, args[0]->collation.repertoire); max_length= args[0]->max_length; + return FALSE; } @@ -3437,7 +3476,7 @@ String *Item_func_collation::val_str(String *str) } -void Item_func_weight_string::fix_length_and_dec() +bool Item_func_weight_string::fix_length_and_dec() { CHARSET_INFO *cs= args[0]->collation.collation; collation.set(&my_charset_bin, args[0]->collation.derivation); @@ -3455,6 +3494,7 @@ void Item_func_weight_string::fix_length_and_dec() max_length= cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen); } maybe_null= 1; + return FALSE; } @@ -3838,15 +3878,16 @@ String* Item_func_export_set::val_str(String* str) return str; } -void Item_func_export_set::fix_length_and_dec() +bool Item_func_export_set::fix_length_and_dec() { uint32 length= MY_MAX(args[1]->max_char_length(), args[2]->max_char_length()); uint32 sep_length= (arg_count > 3 ? args[3]->max_char_length() : 1); if (agg_arg_charsets_for_string_result(collation, args + 1, MY_MIN(4, arg_count) - 1)) - return; + return TRUE; fix_char_length(length * 64 + sep_length * 63); + return FALSE; } @@ -4246,12 +4287,13 @@ bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref) } -void Item_func_dyncol_create::fix_length_and_dec() +bool Item_func_dyncol_create::fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; maybe_null= TRUE; collation.set(&my_charset_bin); decimals= 0; + return FALSE; } bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index c9956ab364e..a908aba2d2f 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -145,9 +145,10 @@ class Item_func_md5 :public Item_str_ascii_checksum_func public: Item_func_md5(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {} String *val_str_ascii(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { fix_length_and_charset(32, default_charset()); + return FALSE; } const char *func_name() const { return "md5"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -160,7 +161,7 @@ class Item_func_sha :public Item_str_ascii_checksum_func public: Item_func_sha(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {} String *val_str_ascii(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "sha"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_sha>(thd, mem_root, this); } @@ -172,7 +173,7 @@ class Item_func_sha2 :public Item_str_ascii_checksum_func Item_func_sha2(THD *thd, Item *a, Item *b) :Item_str_ascii_checksum_func(thd, a, b) {} String *val_str_ascii(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "sha2"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_sha2>(thd, mem_root, this); } @@ -185,7 +186,7 @@ class Item_func_to_base64 :public Item_str_ascii_checksum_func Item_func_to_base64(THD *thd, Item *a) :Item_str_ascii_checksum_func(thd, a) {} String *val_str_ascii(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "to_base64"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_to_base64>(thd, mem_root, this); } @@ -198,7 +199,7 @@ class Item_func_from_base64 :public Item_str_binary_checksum_func Item_func_from_base64(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) { } String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "from_base64"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_from_base64>(thd, mem_root, this); } @@ -225,7 +226,7 @@ class Item_func_aes_encrypt :public Item_aes_crypt public: Item_func_aes_encrypt(THD *thd, Item *a, Item *b) :Item_aes_crypt(thd, a, b) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "aes_encrypt"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_aes_encrypt>(thd, mem_root, this); } @@ -236,7 +237,7 @@ class Item_func_aes_decrypt :public Item_aes_crypt public: Item_func_aes_decrypt(THD *thd, Item *a, Item *b): Item_aes_crypt(thd, a, b) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "aes_decrypt"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_aes_decrypt>(thd, mem_root, this); } @@ -251,7 +252,7 @@ class Item_func_concat :public Item_str_func Item_func_concat(THD *thd, List<Item> &list): Item_str_func(thd, list) {} Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "concat"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_concat>(thd, mem_root, this); } @@ -263,11 +264,12 @@ class Item_func_decode_histogram :public Item_str_func Item_func_decode_histogram(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(system_charset_info); max_length= MAX_BLOB_WIDTH; maybe_null= 1; + return FALSE; } const char *func_name() const { return "decode_histogram"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -280,7 +282,7 @@ class Item_func_concat_ws :public Item_str_func public: Item_func_concat_ws(THD *thd, List<Item> &list): Item_str_func(thd, list) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "concat_ws"; } table_map not_null_tables() const { return 0; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -293,7 +295,7 @@ class Item_func_reverse :public Item_str_func public: Item_func_reverse(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "reverse"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_reverse>(thd, mem_root, this); } @@ -307,7 +309,7 @@ class Item_func_replace :public Item_str_func Item_func_replace(THD *thd, Item *org, Item *find, Item *replace): Item_str_func(thd, org, find, replace) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "replace"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_replace>(thd, mem_root, this); } @@ -333,7 +335,7 @@ class Item_func_regexp_replace :public Item_str_func } String *val_str(String *str); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "regexp_replace"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0;} }; @@ -355,7 +357,7 @@ class Item_func_regexp_substr :public Item_str_func } String *val_str(String *str); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "regexp_substr"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } }; @@ -369,7 +371,7 @@ class Item_func_insert :public Item_str_func Item *new_str): Item_str_func(thd, org, start, length, new_str) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "insert"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_insert>(thd, mem_root, this); } @@ -393,7 +395,7 @@ class Item_func_lcase :public Item_str_conv public: Item_func_lcase(THD *thd, Item *item): Item_str_conv(thd, item) {} const char *func_name() const { return "lcase"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_lcase>(thd, mem_root, this); } }; @@ -403,7 +405,7 @@ class Item_func_ucase :public Item_str_conv public: Item_func_ucase(THD *thd, Item *item): Item_str_conv(thd, item) {} const char *func_name() const { return "ucase"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_ucase>(thd, mem_root, this); } }; @@ -415,7 +417,7 @@ class Item_func_left :public Item_str_func public: Item_func_left(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "left"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_left>(thd, mem_root, this); } @@ -428,7 +430,7 @@ class Item_func_right :public Item_str_func public: Item_func_right(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "right"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_right>(thd, mem_root, this); } @@ -442,7 +444,7 @@ class Item_func_substr :public Item_str_func Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "substr"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_substr>(thd, mem_root, this); } @@ -456,7 +458,7 @@ class Item_func_substr_index :public Item_str_func Item_func_substr_index(THD *thd, Item *a,Item *b,Item *c): Item_str_func(thd, a, b, c) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "substring_index"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_substr_index>(thd, mem_root, this); } @@ -488,7 +490,7 @@ class Item_func_trim :public Item_str_func Item_func_trim(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_func_trim(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "trim"; } void print(String *str, enum_query_type query_type); virtual const char *mode_name() const { return "both"; } @@ -546,12 +548,13 @@ class Item_func_password :public Item_str_ascii_checksum_func Item_str_ascii_checksum_func(thd, a), alg(al), deflt(0) {} String *val_str_ascii(String *str); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec() + bool fix_length_and_dec() { fix_length_and_charset((alg == 1 ? SCRAMBLED_PASSWORD_CHAR_LENGTH : SCRAMBLED_PASSWORD_CHAR_LENGTH_323), default_charset()); + return FALSE; } const char *func_name() const { return ((deflt || alg == 1) ? "password" : "old_password"); } @@ -572,11 +575,12 @@ class Item_func_des_encrypt :public Item_str_binary_checksum_func Item_func_des_encrypt(THD *thd, Item *a, Item *b) :Item_str_binary_checksum_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { maybe_null=1; /* 9 = MAX ((8- (arg_len % 8)) + 1) */ max_length = args[0]->max_length + 9; + return FALSE; } const char *func_name() const { return "des_encrypt"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -592,13 +596,14 @@ class Item_func_des_decrypt :public Item_str_binary_checksum_func Item_func_des_decrypt(THD *thd, Item *a, Item *b) :Item_str_binary_checksum_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { maybe_null=1; /* 9 = MAX ((8- (arg_len % 8)) + 1) */ max_length= args[0]->max_length; if (max_length >= 9U) max_length-= 9U; + return FALSE; } const char *func_name() const { return "des_decrypt"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -631,7 +636,7 @@ class Item_func_encrypt :public Item_str_binary_checksum_func constructor_helper(); } String *val_str(String *); - void fix_length_and_dec() { maybe_null=1; max_length = 13; } + bool fix_length_and_dec() { maybe_null=1; max_length = 13; return FALSE; } const char *func_name() const { return "encrypt"; } bool check_vcol_func_processor(void *arg) { @@ -655,7 +660,7 @@ class Item_func_encode :public Item_str_binary_checksum_func Item_func_encode(THD *thd, Item *a, Item *seed_arg): Item_str_binary_checksum_func(thd, a, seed_arg) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "encode"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_encode>(thd, mem_root, this); } @@ -705,10 +710,11 @@ class Item_func_database :public Item_func_sysconst public: Item_func_database(THD *thd): Item_func_sysconst(thd) {} String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen; maybe_null=1; + return FALSE; } const char *func_name() const { return "database"; } const char *fully_qualified_func_name() const { return "database()"; } @@ -733,10 +739,11 @@ class Item_func_user :public Item_func_sysconst return (null_value ? 0 : &str_value); } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec() + bool fix_length_and_dec() { max_length= (uint32) (username_char_length + HOSTNAME_LENGTH + 1) * SYSTEM_CHARSET_MBMAXLEN; + return FALSE; } const char *func_name() const { return "user"; } const char *fully_qualified_func_name() const { return "user()"; } @@ -776,8 +783,11 @@ class Item_func_current_role :public Item_func_sysconst Item_func_current_role(THD *thd, Name_resolution_context *context_arg): Item_func_sysconst(thd), context(context_arg) {} bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec() - { max_length= (uint32) username_char_length * SYSTEM_CHARSET_MBMAXLEN; } + bool fix_length_and_dec() + { + max_length= (uint32) username_char_length * SYSTEM_CHARSET_MBMAXLEN; + return FALSE; + } int save_in_field(Field *field, bool no_conversions) { return save_str_value_in_field(field, &str_value); } const char *func_name() const { return "current_role"; } @@ -805,7 +815,7 @@ class Item_func_soundex :public Item_str_func public: Item_func_soundex(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "soundex"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_soundex>(thd, mem_root, this); } @@ -819,7 +829,7 @@ class Item_func_elt :public Item_str_func double val_real(); longlong val_int(); String *val_str(String *str); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "elt"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_elt>(thd, mem_root, this); } @@ -833,7 +843,7 @@ class Item_func_make_set :public Item_str_func public: Item_func_make_set(THD *thd, List<Item> &list): Item_str_func(thd, list) {} String *val_str(String *str); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "make_set"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_make_set>(thd, mem_root, this); } @@ -851,7 +861,7 @@ class Item_func_format :public Item_str_ascii_func MY_LOCALE *get_locale(Item *item); String *val_str_ascii(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "format"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_format>(thd, mem_root, this); } @@ -867,9 +877,10 @@ class Item_func_char :public Item_str_func Item_str_func(thd, list) { collation.set(cs); } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { max_length= arg_count * 4; + return FALSE; } const char *func_name() const { return "char"; } void print(String *str, enum_query_type query_type); @@ -885,7 +896,7 @@ class Item_func_repeat :public Item_str_func Item_func_repeat(THD *thd, Item *arg1, Item *arg2): Item_str_func(thd, arg1, arg2) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "repeat"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_repeat>(thd, mem_root, this); } @@ -897,7 +908,7 @@ class Item_func_space :public Item_str_func public: Item_func_space(THD *thd, Item *arg1): Item_str_func(thd, arg1) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "space"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_space>(thd, mem_root, this); } @@ -910,7 +921,7 @@ class Item_func_binlog_gtid_pos :public Item_str_func Item_func_binlog_gtid_pos(THD *thd, Item *arg1, Item *arg2): Item_str_func(thd, arg1, arg2) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "binlog_gtid_pos"; } bool check_vcol_func_processor(void *arg) { @@ -928,7 +939,7 @@ class Item_func_rpad :public Item_str_func Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_str_func(thd, arg1, arg2, arg3) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "rpad"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_rpad>(thd, mem_root, this); } @@ -942,7 +953,7 @@ class Item_func_lpad :public Item_str_func Item_func_lpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_str_func(thd, arg1, arg2, arg3) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "lpad"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_lpad>(thd, mem_root, this); } @@ -956,11 +967,12 @@ class Item_func_conv :public Item_str_func Item_str_func(thd, a, b, c) {} const char *func_name() const { return "conv"; } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(default_charset()); max_length=64; maybe_null= 1; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_conv>(thd, mem_root, this); } @@ -975,11 +987,12 @@ class Item_func_hex :public Item_str_ascii_checksum_func Item_str_ascii_checksum_func(thd, a) {} const char *func_name() const { return "hex"; } String *val_str_ascii(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(default_charset()); decimals=0; fix_char_length(args[0]->max_length * 2); + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_hex>(thd, mem_root, this); } @@ -996,11 +1009,12 @@ class Item_func_unhex :public Item_str_func } const char *func_name() const { return "unhex"; } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(&my_charset_bin); decimals=0; max_length=(1+args[0]->max_length)/2; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_unhex>(thd, mem_root, this); } @@ -1019,11 +1033,12 @@ class Item_func_like_range :public Item_str_func Item_str_func(thd, a, b), is_min(is_min_arg) { maybe_null= 1; } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(args[0]->collation); decimals=0; max_length= MAX_BLOB_WIDTH; + return FALSE; } }; @@ -1064,10 +1079,11 @@ class Item_func_binary :public Item_str_func tmp->set_charset(&my_charset_bin); return tmp; } - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(&my_charset_bin); max_length=args[0]->max_length; + return FALSE; } void print(String *str, enum_query_type query_type); const char *func_name() const { return "cast_as_binary"; } @@ -1084,11 +1100,12 @@ class Item_load_file :public Item_str_func Item_load_file(THD *thd, Item *a): Item_str_func(thd, a) {} String *val_str(String *); const char *func_name() const { return "load_file"; } - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(&my_charset_bin, DERIVATION_COERCIBLE); maybe_null=1; max_length=MAX_BLOB_WIDTH; + return FALSE; } bool check_vcol_func_processor(void *arg) { @@ -1109,7 +1126,7 @@ class Item_func_export_set: public Item_str_func Item_func_export_set(THD *thd, Item *a, Item *b, Item* c, Item* d, Item* e): Item_str_func(thd, a, b, c, d, e) {} String *val_str(String *str); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "export_set"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_export_set>(thd, mem_root, this); } @@ -1123,12 +1140,13 @@ class Item_func_quote :public Item_str_func Item_func_quote(THD *thd, Item *a): Item_str_func(thd, a) {} const char *func_name() const { return "quote"; } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(args[0]->collation); ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 + 2 * collation.collation->mbmaxlen; max_length= (uint32) MY_MIN(max_result_length, MAX_BLOB_WIDTH); + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_quote>(thd, mem_root, this); } @@ -1211,7 +1229,7 @@ class Item_func_conv_charset :public Item_str_func return 1; return res; } - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const { return "convert"; } void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1224,7 +1242,7 @@ class Item_func_set_collation :public Item_str_func Item_func_set_collation(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; const char *func_name() const { return "collate"; } enum precedence precedence() const { return COLLATE_PRECEDENCE; } @@ -1245,11 +1263,12 @@ class Item_func_expr_str_metadata :public Item_str_func { public: Item_func_expr_str_metadata(THD *thd, Item *a): Item_str_func(thd, a) { } - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(system_charset_info); max_length= 64 * collation.collation->mbmaxlen; // should be enough maybe_null= 0; + return FALSE; }; table_map not_null_tables() const { return 0; } Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) @@ -1299,7 +1318,7 @@ class Item_func_weight_string :public Item_str_func } const char *func_name() const { return "weight_string"; } String *val_str(String *); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const { if (!Item_str_func::eq(item, binary_cmp)) @@ -1323,7 +1342,7 @@ class Item_func_crc32 :public Item_int_func Item_func_crc32(THD *thd, Item *a): Item_int_func(thd, a) { unsigned_flag= 1; } const char *func_name() const { return "crc32"; } - void fix_length_and_dec() { max_length=10; } + bool fix_length_and_dec() { max_length=10; return FALSE; } longlong val_int(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_crc32>(thd, mem_root, this); } @@ -1335,7 +1354,7 @@ class Item_func_uncompressed_length : public Item_int_func public: Item_func_uncompressed_length(THD *thd, Item *a): Item_int_func(thd, a) {} const char *func_name() const{return "uncompressed_length";} - void fix_length_and_dec() { max_length=10; maybe_null= true; } + bool fix_length_and_dec() { max_length=10; maybe_null= true; return FALSE; } longlong val_int(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_uncompressed_length>(thd, mem_root, this); } @@ -1353,7 +1372,11 @@ class Item_func_compress: public Item_str_binary_checksum_func public: Item_func_compress(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) {} - void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} + bool fix_length_and_dec() + { + max_length= (args[0]->max_length * 120) / 100 + 12; + return FALSE; + } const char *func_name() const{return "compress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1366,7 +1389,11 @@ class Item_func_uncompress: public Item_str_binary_checksum_func public: Item_func_uncompress(THD *thd, Item *a) :Item_str_binary_checksum_func(thd, a) {} - void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; } + bool fix_length_and_dec() + { + maybe_null= 1; max_length= MAX_BLOB_WIDTH; + return FALSE; + } const char *func_name() const{return "uncompress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1378,11 +1405,12 @@ class Item_func_uuid: public Item_str_func { public: Item_func_uuid(THD *thd): Item_str_func(thd) {} - void fix_length_and_dec() + bool fix_length_and_dec() { collation.set(system_charset_info, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); fix_char_length(MY_UUID_STRING_LENGTH); + return FALSE; } bool const_item() const { return false; } table_map used_tables() const { return RAND_TABLE_BIT; } @@ -1410,7 +1438,7 @@ class Item_func_dyncol_create: public Item_str_func public: Item_func_dyncol_create(THD *thd, List<Item> &args, DYNCALL_CREATE_DEF *dfs); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); const char *func_name() const{ return "column_create"; } String *val_str(String *); void print(String *str, enum_query_type query_type); @@ -1440,11 +1468,12 @@ class Item_func_dyncol_json: public Item_str_func {collation.set(DYNCOL_UTF);} const char *func_name() const{ return "column_json"; } String *val_str(String *); - void fix_length_and_dec() + bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; maybe_null= 1; decimals= 0; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_dyncol_json>(thd, mem_root, this); } @@ -1459,8 +1488,8 @@ class Item_dyncol_get: public Item_str_func public: Item_dyncol_get(THD *thd, Item *str, Item *num): Item_str_func(thd, str, num) {} - void fix_length_and_dec() - { maybe_null= 1;; max_length= MAX_BLOB_WIDTH; } + bool fix_length_and_dec() + { maybe_null= 1;; max_length= MAX_BLOB_WIDTH; return FALSE; } /* Mark that collation can change between calls */ bool dynamic_result() { return 1; } @@ -1498,7 +1527,8 @@ class Item_func_dyncol_list: public Item_str_func public: Item_func_dyncol_list(THD *thd, Item *str): Item_str_func(thd, str) {collation.set(DYNCOL_UTF);} - void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; }; + bool fix_length_and_dec() + { maybe_null= 1; max_length= MAX_BLOB_WIDTH; return FALSE; }; const char *func_name() const{ return "column_list"; } String *val_str(String *); Item *get_copy(THD *thd, MEM_ROOT *mem_root) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 4214980c36c..ca49e06a9e7 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -307,7 +307,8 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) goto end; } - fix_length_and_dec(); + if (fix_length_and_dec()) + goto end; } else goto end; @@ -904,9 +905,10 @@ Item::Type Item_subselect::type() const } -void Item_subselect::fix_length_and_dec() +bool Item_subselect::fix_length_and_dec() { engine->fix_length_and_dec(0); + return FALSE; } @@ -1194,7 +1196,7 @@ enum_field_types Item_singlerow_subselect::field_type() const return engine->field_type(); } -void Item_singlerow_subselect::fix_length_and_dec() +bool Item_singlerow_subselect::fix_length_and_dec() { if ((max_columns= engine->cols()) == 1) { @@ -1204,7 +1206,7 @@ void Item_singlerow_subselect::fix_length_and_dec() { if (!(row= (Item_cache**) current_thd->alloc(sizeof(Item_cache*) * max_columns))) - return; + return TRUE; engine->fix_length_and_dec(row); value= *row; } @@ -1221,6 +1223,7 @@ void Item_singlerow_subselect::fix_length_and_dec() for (uint i= 0; i < max_columns; i++) row[i]->maybe_null= TRUE; } + return FALSE; } @@ -1505,7 +1508,7 @@ void Item_exists_subselect::init_length_and_dec() } -void Item_exists_subselect::fix_length_and_dec() +bool Item_exists_subselect::fix_length_and_dec() { DBUG_ENTER("Item_exists_subselect::fix_length_and_dec"); init_length_and_dec(); @@ -1516,11 +1519,11 @@ void Item_exists_subselect::fix_length_and_dec() thd->change_item_tree(&unit->global_parameters()->select_limit, new (thd->mem_root) Item_int(thd, (int32) 1)); DBUG_PRINT("info", ("Set limit to 1")); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } -void Item_in_subselect::fix_length_and_dec() +bool Item_in_subselect::fix_length_and_dec() { DBUG_ENTER("Item_in_subselect::fix_length_and_dec"); init_length_and_dec(); @@ -1528,7 +1531,7 @@ void Item_in_subselect::fix_length_and_dec() Unlike Item_exists_subselect, LIMIT 1 is set later for Item_in_subselect, depending on the chosen strategy. */ - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 7e99e2c3075..f44a5c4d0ce 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -196,7 +196,7 @@ class Item_subselect :public Item_result_field, const_item_cache= 0; forced_const= TRUE; } - virtual void fix_length_and_dec(); + virtual bool fix_length_and_dec(); table_map used_tables() const; table_map not_null_tables() const { return 0; } bool const_item() const; @@ -306,7 +306,7 @@ class Item_singlerow_subselect :public Item_subselect enum Item_result result_type() const; enum Item_result cmp_type() const; enum_field_types field_type() const; - void fix_length_and_dec(); + bool fix_length_and_dec(); uint cols(); Item* element_index(uint i) { return reinterpret_cast<Item*>(row[i]); } @@ -403,7 +403,7 @@ class Item_exists_subselect :public Item_subselect my_decimal *val_decimal(my_decimal *); bool val_bool(); bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); void print(String *str, enum_query_type query_type); bool select_transformer(JOIN *join); void top_level_item() { abort_on_null=1; } @@ -626,7 +626,7 @@ class Item_in_subselect :public Item_exists_subselect void print(String *str, enum_query_type query_type); enum precedence precedence() const { return CMP_PRECEDENCE; } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); bool const_item() const { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 94569aa66c9..9da0d9acce5 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1131,9 +1131,8 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) result_field=0; max_length=float_length(decimals); null_value=1; - fix_length_and_dec(); - - if (check_sum_func(thd, ref)) + if (fix_length_and_dec() || + check_sum_func(thd, ref)) return TRUE; memcpy (orig_args, args, sizeof (Item *) * arg_count); @@ -1187,9 +1186,8 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) maybe_null= 1; result_field=0; null_value=1; - fix_length_and_dec(); - - if (check_sum_func(thd, ref)) + if (fix_length_and_dec() || + check_sum_func(thd, ref)) return TRUE; orig_args[0]= args[0]; @@ -1327,7 +1325,7 @@ void Item_sum_sum::clear() } -void Item_sum_sum::fix_length_and_dec() +bool Item_sum_sum::fix_length_and_dec() { DBUG_ENTER("Item_sum_sum::fix_length_and_dec"); maybe_null=null_value=1; @@ -1362,7 +1360,7 @@ void Item_sum_sum::fix_length_and_dec() "--ILLEGAL!!!--"), max_length, (int)decimals)); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -1662,9 +1660,10 @@ void Item_sum_count::cleanup() /* Avgerage */ -void Item_sum_avg::fix_length_and_dec() +bool Item_sum_avg::fix_length_and_dec() { - Item_sum_sum::fix_length_and_dec(); + if (Item_sum_sum::fix_length_and_dec()) + return TRUE; maybe_null=null_value=1; prec_increment= current_thd->variables.div_precincrement; if (Item_sum_avg::result_type() == DECIMAL_RESULT) @@ -1684,6 +1683,7 @@ void Item_sum_avg::fix_length_and_dec() FLOATING_POINT_DECIMALS); max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals)); } + return FALSE; } @@ -1882,7 +1882,7 @@ Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item): } -void Item_sum_variance::fix_length_and_dec() +bool Item_sum_variance::fix_length_and_dec() { DBUG_ENTER("Item_sum_variance::fix_length_and_dec"); maybe_null= null_value= 1; @@ -1917,7 +1917,7 @@ void Item_sum_variance::fix_length_and_dec() DBUG_ASSERT(0); } DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals)); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -2987,13 +2987,13 @@ my_decimal *Item_sum_udf_int::val_decimal(my_decimal *dec) /** Default max_length is max argument length. */ -void Item_sum_udf_str::fix_length_and_dec() +bool Item_sum_udf_str::fix_length_and_dec() { DBUG_ENTER("Item_sum_udf_str::fix_length_and_dec"); max_length=0; for (uint i = 0; i < arg_count; i++) set_if_bigger(max_length,args[i]->max_length); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } diff --git a/sql/item_sum.h b/sql/item_sum.h index 5c446e5779d..5c8ff520259 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -457,7 +457,8 @@ class Item_sum :public Item_func_or_sum */ virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } - virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } + virtual bool fix_length_and_dec() + { maybe_null=1; null_value=1; return FALSE; } virtual Item *result_item(THD *thd, Field *field); void update_used_tables (); @@ -752,8 +753,8 @@ class Item_sum_int :public Item_sum_num my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } - void fix_length_and_dec() - { decimals=0; max_length=21; maybe_null=null_value=0; } + bool fix_length_and_dec() + { decimals=0; max_length=21; maybe_null=null_value=0; return FALSE; } }; @@ -764,7 +765,7 @@ class Item_sum_sum :public Item_sum_num, double sum; my_decimal dec_buffs[2]; uint curr_dec_buff; - void fix_length_and_dec(); + bool fix_length_and_dec(); public: Item_sum_sum(THD *thd, Item *item_par, bool distinct): @@ -888,7 +889,7 @@ class Item_sum_avg :public Item_sum_sum :Item_sum_sum(thd, item), count(item->count), prec_increment(item->prec_increment) {} - void fix_length_and_dec(); + bool fix_length_and_dec(); enum Sumfunctype sum_func () const { return has_with_distinct() ? AVG_DISTINCT_FUNC : AVG_FUNC; @@ -948,7 +949,7 @@ But, this falls prey to catastrophic cancellation. Instead, use the recurrence class Item_sum_variance : public Item_sum_num { - void fix_length_and_dec(); + bool fix_length_and_dec(); public: double recurrence_m, recurrence_s; /* Used in recurrence relation. */ @@ -1110,8 +1111,11 @@ class Item_sum_bit :public Item_sum_int longlong val_int(); void reset_field(); void update_field(); - void fix_length_and_dec() - { decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; } + bool fix_length_and_dec() + { + decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; + return FALSE; + } void cleanup() { bits= reset_bits; @@ -1401,7 +1405,7 @@ class Item_sum_udf_float :public Item_udf_sum enum Item_result result_type () const { return REAL_RESULT; } enum Item_result cmp_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() { fix_num_length_and_dec(); } + bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } Item *copy_or_same(THD* thd); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_sum_udf_float>(thd, mem_root, this); } @@ -1424,7 +1428,7 @@ class Item_sum_udf_int :public Item_udf_sum my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } - void fix_length_and_dec() { decimals=0; max_length=21; } + bool fix_length_and_dec() { decimals=0; max_length=21; return FALSE; } Item *copy_or_same(THD* thd); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_sum_udf_int>(thd, mem_root, this); } @@ -1466,7 +1470,7 @@ class Item_sum_udf_str :public Item_udf_sum my_decimal *val_decimal(my_decimal *dec); enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return string_field_type(); } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *copy_or_same(THD* thd); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_sum_udf_str>(thd, mem_root, this); } @@ -1488,7 +1492,7 @@ class Item_sum_udf_decimal :public Item_udf_sum my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return DECIMAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } - void fix_length_and_dec() { fix_num_length_and_dec(); } + bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } Item *copy_or_same(THD* thd); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_sum_udf_decimal>(thd, mem_root, this); } @@ -1563,7 +1567,7 @@ class Item_sum_udf_str :public Item_sum_num double val_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; } longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() { maybe_null=1; max_length=0; } + bool fix_length_and_dec() { maybe_null=1; max_length=0; return FALSE; } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } void clear() {} bool add() { return 0; } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 87c6489189c..bb75ad7c28c 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -953,7 +953,7 @@ longlong Item_func_month::val_int() } -void Item_func_monthname::fix_length_and_dec() +bool Item_func_monthname::fix_length_and_dec() { THD* thd= current_thd; CHARSET_INFO *cs= thd->variables.collation_connection; @@ -961,7 +961,8 @@ void Item_func_monthname::fix_length_and_dec() collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire()); decimals=0; max_length= locale->max_month_name_length * collation.collation->mbmaxlen; - maybe_null=1; + maybe_null=1; + return FALSE; } @@ -1101,7 +1102,7 @@ longlong Item_func_weekday::val_int() odbc_type) + MY_TEST(odbc_type); } -void Item_func_dayname::fix_length_and_dec() +bool Item_func_dayname::fix_length_and_dec() { THD* thd= current_thd; CHARSET_INFO *cs= thd->variables.collation_connection; @@ -1109,7 +1110,8 @@ void Item_func_dayname::fix_length_and_dec() collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire()); decimals=0; max_length= locale->max_day_name_length * collation.collation->mbmaxlen; - maybe_null=1; + maybe_null=1; + return FALSE; } @@ -1476,7 +1478,7 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) } -void Item_temporal_func::fix_length_and_dec() +bool Item_temporal_func::fix_length_and_dec() { uint char_length= mysql_temporal_int_part_length(field_type()); /* @@ -1502,6 +1504,7 @@ void Item_temporal_func::fix_length_and_dec() DERIVATION_COERCIBLE : DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); fix_char_length(char_length); + return FALSE; } String *Item_temporal_func::val_str(String *str) @@ -1873,7 +1876,7 @@ bool Item_func_sec_to_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) return 0; } -void Item_func_date_format::fix_length_and_dec() +bool Item_func_date_format::fix_length_and_dec() { THD* thd= current_thd; locale= thd->variables.lc_time_names; @@ -1904,6 +1907,7 @@ void Item_func_date_format::fix_length_and_dec() set_if_smaller(max_length,MAX_BLOB_WIDTH); } maybe_null=1; // If wrong date + return FALSE; } @@ -2050,13 +2054,13 @@ String *Item_func_date_format::val_str(String *str) } -void Item_func_from_unixtime::fix_length_and_dec() -{ +bool Item_func_from_unixtime::fix_length_and_dec() +{ THD *thd= current_thd; thd->time_zone_used= 1; tz= thd->variables.time_zone; decimals= args[0]->decimals; - Item_temporal_func::fix_length_and_dec(); + return Item_temporal_func::fix_length_and_dec(); } @@ -2083,10 +2087,10 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime, } -void Item_func_convert_tz::fix_length_and_dec() +bool Item_func_convert_tz::fix_length_and_dec() { decimals= args[0]->temporal_precision(MYSQL_TYPE_DATETIME); - Item_temporal_func::fix_length_and_dec(); + return Item_temporal_func::fix_length_and_dec(); } @@ -2135,7 +2139,7 @@ void Item_func_convert_tz::cleanup() } -void Item_date_add_interval::fix_length_and_dec() +bool Item_date_add_interval::fix_length_and_dec() { enum_field_types arg0_field_type; @@ -2190,7 +2194,7 @@ void Item_date_add_interval::fix_length_and_dec() } else decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec); - Item_temporal_func::fix_length_and_dec(); + return Item_temporal_func::fix_length_and_dec(); } @@ -2261,7 +2265,7 @@ void Item_extract::print(String *str, enum_query_type query_type) str->append(')'); } -void Item_extract::fix_length_and_dec() +bool Item_extract::fix_length_and_dec() { maybe_null=1; // If wrong date switch (int_type) { @@ -2287,6 +2291,7 @@ void Item_extract::fix_length_and_dec() case INTERVAL_SECOND_MICROSECOND: set_time_length(8); break; // ssffffff case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ } + return FALSE; } @@ -2548,7 +2553,7 @@ String *Item_char_typecast::val_str(String *str) } -void Item_char_typecast::fix_length_and_dec() +bool Item_char_typecast::fix_length_and_dec() { uint32 char_length; /* @@ -2594,6 +2599,7 @@ void Item_char_typecast::fix_length_and_dec() (cast_cs == &my_charset_bin ? 1 : args[0]->collation.collation->mbmaxlen)); max_length= char_length * cast_cs->mbmaxlen; + return FALSE; } @@ -2682,7 +2688,7 @@ bool Item_func_makedate::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } -void Item_func_add_time::fix_length_and_dec() +bool Item_func_add_time::fix_length_and_dec() { enum_field_types arg0_field_type; decimals= MY_MAX(args[0]->decimals, args[1]->decimals); @@ -2714,7 +2720,7 @@ void Item_func_add_time::fix_length_and_dec() decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), args[1]->temporal_precision(MYSQL_TYPE_TIME)); } - Item_temporal_func::fix_length_and_dec(); + return Item_temporal_func::fix_length_and_dec(); } /** @@ -3203,10 +3209,10 @@ get_date_time_result_type(const char *format, uint length) } -void Item_func_str_to_date::fix_length_and_dec() +bool Item_func_str_to_date::fix_length_and_dec() { if (agg_arg_charsets(collation, args, 2, MY_COLL_ALLOW_CONV, 1)) - return; + return TRUE; if (collation.collation->mbminlen > 1) { #if MYSQL_VERSION_ID > 50500 @@ -3249,7 +3255,7 @@ void Item_func_str_to_date::fix_length_and_dec() } } cached_timestamp_type= mysql_type_to_time_type(field_type()); - Item_temporal_func::fix_length_and_dec(); + return Item_temporal_func::fix_length_and_dec(); } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 354a54a5c1a..c983e1a6f8a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -49,9 +49,10 @@ class Item_func_period_add :public Item_int_func Item_func_period_add(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "period_add"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_period_add>(thd, mem_root, this); } @@ -64,10 +65,11 @@ class Item_func_period_diff :public Item_int_func Item_func_period_diff(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "period_diff"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_period_diff>(thd, mem_root, this); } @@ -80,11 +82,12 @@ class Item_func_to_days :public Item_int_func Item_func_to_days(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "to_days"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + maybe_null=1; + return FALSE; } enum_monotonicity_info get_monotonicity_info() const; longlong val_int_endpoint(bool left_endp, bool *incl_endp); @@ -105,11 +108,12 @@ class Item_func_to_seconds :public Item_int_func Item_func_to_seconds(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "to_seconds"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null= 1; + return FALSE; } enum_monotonicity_info get_monotonicity_info() const; longlong val_int_endpoint(bool left_endp, bool *incl_endp); @@ -131,11 +135,12 @@ class Item_func_dayofmonth :public Item_int_func Item_func_dayofmonth(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "dayofmonth"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -167,11 +172,12 @@ class Item_func_month :public Item_func const char *func_name() const { return "month"; } enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals= 0; fix_char_length(2); maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -191,7 +197,7 @@ class Item_func_monthname :public Item_str_func Item_func_monthname(THD *thd, Item *a): Item_str_func(thd, a) {} const char *func_name() const { return "monthname"; } String *val_str(String *str); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool check_partition_func_processor(void *int_arg) {return TRUE;} bool check_valid_arguments_processor(void *int_arg) { @@ -212,11 +218,12 @@ class Item_func_dayofyear :public Item_int_func Item_func_dayofyear(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "dayofyear"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals= 0; fix_char_length(3); maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -235,11 +242,12 @@ class Item_func_hour :public Item_int_func Item_func_hour(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "hour"; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -258,11 +266,12 @@ class Item_func_minute :public Item_int_func Item_func_minute(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "minute"; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -281,11 +290,12 @@ class Item_func_quarter :public Item_int_func Item_func_quarter(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "quarter"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -304,11 +314,12 @@ class Item_func_second :public Item_int_func Item_func_second(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "second"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -328,11 +339,12 @@ class Item_func_week :public Item_int_func Item_func_week(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "week"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_vcol_func_processor(void *arg) { @@ -354,11 +366,12 @@ class Item_func_yearweek :public Item_int_func Item_func_yearweek(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "yearweek"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -379,11 +392,12 @@ class Item_func_year :public Item_int_func const char *func_name() const { return "year"; } enum_monotonicity_info get_monotonicity_info() const; longlong val_int_endpoint(bool left_endp, bool *incl_endp); - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -416,11 +430,12 @@ class Item_func_weekday :public Item_func } enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals= 0; fix_char_length(1); maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -441,7 +456,7 @@ class Item_func_dayname :public Item_func_weekday String *val_str(String *str); enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool check_partition_func_processor(void *int_arg) {return TRUE;} bool check_vcol_func_processor(void *arg) { @@ -457,7 +472,7 @@ class Item_func_seconds_hybrid: public Item_func_numhybrid public: Item_func_seconds_hybrid(THD *thd): Item_func_numhybrid(thd) {} Item_func_seconds_hybrid(THD *thd, Item *a): Item_func_numhybrid(thd, a) {} - void fix_length_and_dec() + bool fix_length_and_dec() { if (arg_count) decimals= args[0]->temporal_precision(arg0_expected_type()); @@ -465,6 +480,7 @@ class Item_func_seconds_hybrid: public Item_func_numhybrid max_length=17 + (decimals ? decimals + 1 : 0); maybe_null= true; set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT); + return FALSE; } double real_op() { DBUG_ASSERT(0); return 0; } String *str_op(String *str) { DBUG_ASSERT(0); return 0; } @@ -556,7 +572,7 @@ class Item_temporal_func: public Item_func save_date_in_field(field); } #endif - void fix_length_and_dec(); + bool fix_length_and_dec(); }; @@ -834,7 +850,7 @@ class Item_func_date_format :public Item_str_func String *val_str(String *str); const char *func_name() const { return is_time_format ? "time_format" : "date_format"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; bool check_vcol_func_processor(void *arg) @@ -854,7 +870,7 @@ class Item_func_from_unixtime :public Item_datetimefunc public: Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {} const char *func_name() const { return "from_unixtime"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_from_unixtime>(thd, mem_root, this); } @@ -889,7 +905,7 @@ class Item_func_convert_tz :public Item_datetimefunc Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c): Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {} const char *func_name() const { return "convert_tz"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); void cleanup(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -902,10 +918,10 @@ class Item_func_sec_to_time :public Item_timefunc public: Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {} bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); - void fix_length_and_dec() + bool fix_length_and_dec() { decimals= MY_MIN(args[0]->decimals, TIME_SECOND_PART_DIGITS); - Item_timefunc::fix_length_and_dec(); + return Item_timefunc::fix_length_and_dec(); } const char *func_name() const { return "sec_to_time"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -923,7 +939,7 @@ class Item_date_add_interval :public Item_temporal_hybrid_func Item_temporal_hybrid_func(thd, a, b),int_type(type_arg), date_sub_interval(neg_arg) {} const char *func_name() const { return "date_add_interval"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str, enum_query_type query_type); @@ -991,7 +1007,7 @@ class Item_extract :public Item_int_func longlong val_int(); enum Functype functype() const { return EXTRACT_FUNC; } const char *func_name() const { return "extract"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; void print(String *str, enum_query_type query_type); bool check_partition_func_processor(void *int_arg) {return FALSE;} @@ -1063,7 +1079,7 @@ class Item_char_typecast :public Item_str_func bool eq(const Item *item, bool binary_cmp) const; const char *func_name() const { return "cast_as_char"; } String *val_str(String *a); - void fix_length_and_dec(); + bool fix_length_and_dec(); void print(String *str, enum_query_type query_type); bool need_parentheses_in_default() { return true; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1077,11 +1093,11 @@ class Item_temporal_typecast: public Item_temporal_func Item_temporal_typecast(THD *thd, Item *a): Item_temporal_func(thd, a) {} virtual const char *cast_type() const = 0; void print(String *str, enum_query_type query_type); - void fix_length_and_dec() + bool fix_length_and_dec() { if (decimals == NOT_FIXED_DEC) decimals= args[0]->temporal_precision(field_type()); - Item_temporal_func::fix_length_and_dec(); + return Item_temporal_func::fix_length_and_dec(); } }; @@ -1148,7 +1164,7 @@ class Item_func_add_time :public Item_temporal_hybrid_func Item_func_add_time(THD *thd, Item *a, Item *b, bool type_arg, bool neg_arg): Item_temporal_hybrid_func(thd, a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; } - void fix_length_and_dec(); + bool fix_length_and_dec(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); void print(String *str, enum_query_type query_type); const char *func_name() const { return "add_time"; } @@ -1161,11 +1177,11 @@ class Item_func_timediff :public Item_timefunc public: Item_func_timediff(THD *thd, Item *a, Item *b): Item_timefunc(thd, a, b) {} const char *func_name() const { return "timediff"; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), args[1]->temporal_precision(MYSQL_TYPE_TIME)); - Item_timefunc::fix_length_and_dec(); + return Item_timefunc::fix_length_and_dec(); } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1178,10 +1194,10 @@ class Item_func_maketime :public Item_timefunc Item_func_maketime(THD *thd, Item *a, Item *b, Item *c): Item_timefunc(thd, a, b, c) {} - void fix_length_and_dec() + bool fix_length_and_dec() { decimals= MY_MIN(args[2]->decimals, TIME_SECOND_PART_DIGITS); - Item_timefunc::fix_length_and_dec(); + return Item_timefunc::fix_length_and_dec(); } const char *func_name() const { return "maketime"; } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); @@ -1196,10 +1212,11 @@ class Item_func_microsecond :public Item_int_func Item_func_microsecond(THD *thd, Item *a): Item_int_func(thd, a) {} longlong val_int(); const char *func_name() const { return "microsecond"; } - void fix_length_and_dec() - { + bool fix_length_and_dec() + { decimals=0; maybe_null=1; + return FALSE; } bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} @@ -1220,10 +1237,11 @@ class Item_func_timestamp_diff :public Item_int_func Item_int_func(thd, a, b), int_type(type_arg) {} const char *func_name() const { return "timestampdiff"; } longlong val_int(); - void fix_length_and_dec() + bool fix_length_and_dec() { decimals=0; maybe_null=1; + return FALSE; } virtual void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1245,11 +1263,12 @@ class Item_func_get_format :public Item_str_ascii_func {} String *val_str_ascii(String *str); const char *func_name() const { return "get_format"; } - void fix_length_and_dec() + bool fix_length_and_dec() { maybe_null= 1; decimals=0; fix_length_and_charset(17, default_charset()); + return FALSE; } virtual void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -1271,7 +1290,7 @@ class Item_func_str_to_date :public Item_temporal_hybrid_func {} bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); const char *func_name() const { return "str_to_date"; } - void fix_length_and_dec(); + bool fix_length_and_dec(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_str_to_date>(thd, mem_root, this); } }; diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index 5fbfb2651af..532a351dec1 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -106,7 +106,8 @@ Item_window_func::fix_fields(THD *thd, Item **ref) with_window_func= true; with_sum_func= false; - fix_length_and_dec(); + if (fix_length_and_dec()) + return TRUE; max_length= window_func()->max_length; maybe_null= window_func()->maybe_null; @@ -268,7 +269,8 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref) maybe_null= 1; result_field=0; null_value=1; - fix_length_and_dec(); + if (fix_length_and_dec()) + return TRUE; if (check_sum_func(thd, ref)) return TRUE; diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index a1ef6854288..e5afb9e1555 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -516,10 +516,11 @@ class Item_sum_percent_rank: public Item_sum_window_with_row_count enum Item_result result_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals = 10; // TODO-cvicentiu find out how many decimals the standard // requires. + return FALSE; } void setup_window_func(THD *thd, Window_spec *window_spec); @@ -602,10 +603,11 @@ class Item_sum_cume_dist: public Item_sum_window_with_row_count enum Item_result result_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() + bool fix_length_and_dec() { decimals = 10; // TODO-cvicentiu find out how many decimals the standard // requires. + return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) @@ -950,9 +952,10 @@ class Item_window_func : public Item_func_or_sum void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags); - void fix_length_and_dec() + bool fix_length_and_dec() { decimals = window_func()->decimals; + return FALSE; } const char* func_name() const { return "WF"; } diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index af62a94afd0..738047fea9b 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -222,13 +222,14 @@ class Item_nodeset_func :public Item_str_func return str; } enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() + bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; collation.collation= pxml->charset(); // To avoid premature evaluation, mark all nodeset functions as non-const. used_tables_cache= RAND_TABLE_BIT; const_item_cache= false; + return FALSE; } const char *func_name() const { return "nodeset"; } bool check_vcol_func_processor(void *arg) @@ -456,7 +457,7 @@ class Item_nodeset_context_cache :public Item_nodeset_func Item_nodeset_func(thd, pxml), string_cache(str_arg) { } String *val_nodeset(String *res) { return string_cache; } - void fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; } + bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; return FALSE; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_nodeset_context_cache>(thd, mem_root, this); } }; @@ -470,7 +471,7 @@ class Item_func_xpath_position :public Item_int_func Item_func_xpath_position(THD *thd, Item *a, String *p): Item_int_func(thd, a), pxml(p) {} const char *func_name() const { return "xpath_position"; } - void fix_length_and_dec() { max_length=10; } + bool fix_length_and_dec() { max_length=10; return FALSE; } longlong val_int() { String *flt= args[0]->val_nodeset(&tmp_value); @@ -491,7 +492,7 @@ class Item_func_xpath_count :public Item_int_func Item_func_xpath_count(THD *thd, Item *a, String *p): Item_int_func(thd, a), pxml(p) {} const char *func_name() const { return "xpath_count"; } - void fix_length_and_dec() { max_length=10; } + bool fix_length_and_dec() { max_length=10; return FALSE; } longlong val_int() { uint predicate_supplied_context_size; @@ -2709,10 +2710,10 @@ my_xpath_parse(MY_XPATH *xpath, const char *str, const char *strend) } -void Item_xml_str_func::fix_length_and_dec() +bool Item_xml_str_func::fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; - agg_arg_charsets_for_comparison(collation, args, arg_count); + return agg_arg_charsets_for_comparison(collation, args, arg_count); } diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index d281e076ec8..c46365ee5f0 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -82,7 +82,7 @@ class Item_xml_str_func: public Item_str_func maybe_null= TRUE; } bool fix_fields(THD *thd, Item **ref); - void fix_length_and_dec(); + bool fix_length_and_dec(); bool const_item() const { return const_item_cache && (!nodeset_func || nodeset_func->const_item()); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 30ef26f67e2..3fecddc6661 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13508,7 +13508,8 @@ COND *Item_func_eq::build_equal_items(THD *thd, List_iterator_fast<Item_equal> it(cond_equal.current_level); while ((item_equal= it++)) { - item_equal->fix_length_and_dec(); + if (item_equal->fix_length_and_dec()) + return NULL; item_equal->update_used_tables(); set_if_bigger(thd->lex->current_select->max_equal_elems, item_equal->n_field_items()); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9e7973b745c..f3cb85f01d3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4894,7 +4894,13 @@ int create_table_impl(THD *thd, file= mysql_create_frm_image(thd, orig_db, orig_table_name, create_info, alter_info, create_table_mode, key_info, key_count, frm); - if (!file) + /* + We have to check thd->is_error() here because it can be set by + Item::val* for example, and before it will be cought accidentally by + Item_func::fix_fields() of the next call. Now we removed the check + from Item_func::fix_fields() + */ + if (!file || thd->is_error()) goto err; if (rea_create_table(thd, frm, path, db, table_name, create_info, file, frm_only)) @@ -7377,7 +7383,8 @@ static bool mysql_inplace_alter_table(THD *thd, */ if (mysql_rename_table(db_type, alter_ctx->new_db, alter_ctx->tmp_name, alter_ctx->db, alter_ctx->alias, - FN_FROM_IS_TMP | NO_HA_TABLE)) + FN_FROM_IS_TMP | NO_HA_TABLE) || + thd->is_error()) { // Since changes were done in-place, we can't revert them. (void) quick_rm_table(thd, db_type,
1 0
0 0
[Commits] fa0b71b0e19: MDEV-10259 mysqld crash with certain statement length and...
by sachin 08 May '18

08 May '18
revision-id: fa0b71b0e190403ae65e82a58c3af6c086242c96 (mariadb-10.1.32-83-gfa0b71b0e19) parent(s): de0e5fe17c9e59fc7e16691b00eb32162a2a1409 author: Sachin Setiya committer: Sachin Setiya timestamp: 2018-05-08 17:25:35 +0530 message: MDEV-10259 mysqld crash with certain statement length and... order with Galera and encrypt-tmp-files=1 Problem:- If trans_cache (IO_CACHE) uses encrypted tmp file then on next DML server will crash. Case:- Lets take a case , we have a table t1 , We try to do 2 inserts in t1 1. A really long insert so that trans_cache has to use temp_file 2. Just a small insert Analysis:- Actually server crashes from inside of galera library. /lib64/libc.so.6(abort+0x175)[0x7fb5ba779dc5] /usr/lib64/galera/libgalera_smm.so(_ZN6galera3FSMINS_9TrxHandle5State... mysys/stacktrace.c:247(my_print_stacktrace)[0x7fb5a714940e] sql/signal_handler.cc:160(handle_fatal_signal)[0x7fb5a715c1bd] sql/wsrep_hton.cc:257(wsrep_rollback)[0x7fb5bcce923a] sql/wsrep_hton.cc:268(wsrep_rollback)[0x7fb5bcce9368] sql/handler.cc:1658(ha_rollback_trans(THD*, bool))[0x7fb5bcd4f41a] sql/handler.cc:1483(ha_commit_trans(THD*, bool))[0x7fb5bcd4f804] but actual issue is not in galera but in mariadb, because for 2nd insert we should never call rollback. We are calling rollback because log_and_order fails it fails because write_cache fails , It fails because after reinit_io_cache(trans_cache) , my_b_bytes_in_cache says 0 so we look into tmp_file for data , which is obviously wrong since temp was used for previous insert and it no longer exist. wsrep_write_cache_inc() reads the IO_CACHE in a loop, filling it with my_b_fill() until it returns "0 bytes read". Later MYSQL_BIN_LOG::write_cache() does the same. wsrep_write_cache_inc() assumes that reading a zero bytes past EOF leaves the old data in the cache Solution:- There is two issue in my_b_encr_read 1st we should never equal read_end to info->buffer. I mean this does not make sense read_end should always point to end of buffer. 2nd For most of the case(apart from async IO_CACHE) info->pos_in_file should be equal to info->buffer position wrt to temp file , since in this case we are not changing info->buffer it should remain unchanged. --- .../suite/galera/r/galera_encrypt_tmp_files.result | 35 +++++++++++ .../suite/galera/t/galera_encrypt_tmp_files.cnf | 8 +++ .../suite/galera/t/galera_encrypt_tmp_files.test | 57 ++++++++++++++++++ sql/mf_iocache_encr.cc | 4 +- unittest/sql/mf_iocache-t.cc | 67 +++++++++++++++++++++- 5 files changed, 168 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result b/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result new file mode 100644 index 00000000000..63f6c281af1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result @@ -0,0 +1,35 @@ +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +CREATE TABLE `t1` ( +`col1` int(11) NOT NULL, +`col2` varchar(64) NOT NULL DEFAULT '', +`col3` varchar(32) NOT NULL DEFAULT '0', +`col4` varchar(64) NOT NULL DEFAULT '', +`col5` tinyint(4) NOT NULL DEFAULT '0', +`col6` int(11) NOT NULL DEFAULT '0', +`col7` varchar(64) NOT NULL DEFAULT '', +`col8` tinyint(4) NOT NULL DEFAULT '0', +`col9` tinyint(4) NOT NULL DEFAULT '0', +`col10` text NOT NULL, +`col11` varchar(255) NOT NULL DEFAULT '', +`col12` tinyint(4) NOT NULL DEFAULT '1' +) ; +create table t2 (test int); +insert into t2 values (1); +drop table t1,t2; diff --git a/mysql-test/suite/galera/t/galera_encrypt_tmp_files.cnf b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.cnf new file mode 100644 index 00000000000..0f7f80b7d0b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.cnf @@ -0,0 +1,8 @@ +!include ../galera_2nodes.cnf +[mysqld] + +encrypt-tmp-files = 1 +plugin-load-add= @ENV.FILE_KEY_MANAGEMENT_SO +file-key-management +loose-file-key-management-filename= @ENV.MYSQL_TEST_DIR/std_data/keys.txt +log-bin diff --git a/mysql-test/suite/galera/t/galera_encrypt_tmp_files.test b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.test new file mode 100644 index 00000000000..c42c3dbd98a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.test @@ -0,0 +1,57 @@ +# This file tests that mariadb cluster should not crash when encrypt_tmp_file +# is enabled + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +--connection node_1 + +CREATE TABLE `t1` ( + `col1` int(11) NOT NULL, + `col2` varchar(64) NOT NULL DEFAULT '', + `col3` varchar(32) NOT NULL DEFAULT '0', + `col4` varchar(64) NOT NULL DEFAULT '', + `col5` tinyint(4) NOT NULL DEFAULT '0', + `col6` int(11) NOT NULL DEFAULT '0', + `col7` varchar(64) NOT NULL DEFAULT '', + `col8` tinyint(4) NOT NULL DEFAULT '0', + `col9` tinyint(4) NOT NULL DEFAULT '0', + `col10` text NOT NULL, + `col11` varchar(255) NOT NULL DEFAULT '', + `col12` tinyint(4) NOT NULL DEFAULT '1' +) ; + +#Although we just need $counter >= 907 for IO_CACHE to use +#encrypted temp file. Just on safe side I am using $counter +# = 1100 +--disable_query_log +--let $counter=1100 +--let $query= (1,'test','test','test',0,0,'-1',0,0,'','',-1) +while($counter) +{ + --let $query= $query ,(1,'test','test','test',0,0,'-1',0,0,'','',-1) + --dec $counter +} +--let $query= INSERT INTO t1 values $query ; +--eval $query +--enable_query_log +#INSERT INTO `t1` VALUE + +create table t2 (test int); +insert into t2 values (1); + +drop table t1,t2; diff --git a/sql/mf_iocache_encr.cc b/sql/mf_iocache_encr.cc index 149e6feb605..f26a437a25a 100644 --- a/sql/mf_iocache_encr.cc +++ b/sql/mf_iocache_encr.cc @@ -49,8 +49,8 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count) if (pos_in_file == info->end_of_file) { - info->read_pos= info->read_end= info->buffer; - info->pos_in_file= pos_in_file; + /* reading past EOF should not empty the cache */ + info->read_pos= info->read_end; info->error= 0; DBUG_RETURN(MY_TEST(Count)); } diff --git a/unittest/sql/mf_iocache-t.cc b/unittest/sql/mf_iocache-t.cc index 31f98562521..d5e2ffb095e 100644 --- a/unittest/sql/mf_iocache-t.cc +++ b/unittest/sql/mf_iocache-t.cc @@ -187,10 +187,71 @@ void mdev9044() close_cached_file(&info); } +/* 2 Reads in cache makes second read to fail (only if first read uses temp file) */ +void mdev10259() +{ + int res; + uchar buf[CACHE_SIZE + 200]; + memset(buf, FILL, sizeof(buf)); + + diag("MDEV-10259- mysqld crash with certain statement length and order with" + " Galera and encrypt-tmp-files=1"); + + init_io_cache_encryption(); + + res= open_cached_file(&info, 0, 0, CACHE_SIZE, 0); + ok(res == 0, "open_cached_file" INFO_TAIL); + + res= my_b_write(&info, buf, sizeof(buf)); + ok(res == 0 && info.pos_in_file == CACHE_SIZE, "large write" INFO_TAIL); + + res= my_b_flush_io_cache(&info, 1); + ok(res == 0, "flush" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit READ_CACHE" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == CACHE_SIZE, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 200, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit WRITE_CACHE" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == CACHE_SIZE, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 200, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit WRITE_CACHE" INFO_TAIL); + + res= my_b_read(&info, buf, sizeof(buf)) || data_bad(buf, sizeof(buf)); + ok(res == 0 && info.pos_in_file == CACHE_SIZE, "large read" INFO_TAIL); + + close_cached_file(&info); + +} + int main(int argc __attribute__((unused)),char *argv[]) { MY_INIT(argv[0]); - plan(29); + plan(44); /* temp files with and without encryption */ encrypt_tmp_files= 1; @@ -202,6 +263,10 @@ int main(int argc __attribute__((unused)),char *argv[]) /* regression tests */ mdev9044(); + encrypt_tmp_files= 1; + mdev10259(); + encrypt_tmp_files= 0; + my_end(0); return exit_status(); }
1 0
0 0
[Commits] 9781cfa29c1: MDEV-10259 mysqld crash with certain statement length and...
by sachin 08 May '18

08 May '18
revision-id: 9781cfa29c1314663ef1d0063dcd50cb6772039a (mariadb-10.1.32-83-g9781cfa29c1) parent(s): de0e5fe17c9e59fc7e16691b00eb32162a2a1409 author: Sachin Setiya committer: Sachin Setiya timestamp: 2018-05-08 17:15:18 +0530 message: MDEV-10259 mysqld crash with certain statement length and... order with Galera and encrypt-tmp-files=1 Problem:- If trans_cache (IO_CACHE) uses encrypted tmp file then on next DML server will crash. Case:- Lets take a case , we have a table t1 , We try to do 2 inserts in t1 1. A really long insert so that trans_cache has to use temp_file 2. Just a small insert Analysis:- Actually server crashes from inside of galera library. /lib64/libc.so.6(abort+0x175)[0x7fb5ba779dc5] /usr/lib64/galera/libgalera_smm.so(_ZN6galera3FSMINS_9TrxHandle5State... mysys/stacktrace.c:247(my_print_stacktrace)[0x7fb5a714940e] sql/signal_handler.cc:160(handle_fatal_signal)[0x7fb5a715c1bd] sql/wsrep_hton.cc:257(wsrep_rollback)[0x7fb5bcce923a] sql/wsrep_hton.cc:268(wsrep_rollback)[0x7fb5bcce9368] sql/handler.cc:1658(ha_rollback_trans(THD*, bool))[0x7fb5bcd4f41a] sql/handler.cc:1483(ha_commit_trans(THD*, bool))[0x7fb5bcd4f804] but actual issue is not in galera but in mariadb, because for 2nd insert we should never call rollback. We are calling rollback because log_and_order fails it fails because write_cache fails , It fails because after reinit_io_cache(trans_cache) , my_b_bytes_in_cache says 0 so we look into tmp_file for data , which is obviously wrong since temp was used for previous insert and it no longer exist. wsrep_write_cache_inc() reads the IO_CACHE in a loop, filling it with my_b_fill() until it returns "0 bytes read". Later MYSQL_BIN_LOG::write_cache() does the same. wsrep_write_cache_inc() assumes that reading a zero bytes past EOF leaves the old data in the cache Solution:- There is two issue in my_b_encr_read 1st we should never equal read_end to info->buffer. I mean this does not make sense read_end should always point to end of buffer. 2nd For most of the case(apart from async IO_CACHE) info->pos_in_file should be equal to info->buffer position wrt to temp file , since in this case we are not changing info->buffer it should remain unchanged. --- .../suite/galera/r/galera_encrypt_tmp_files.result | 35 ++++++++++++ .../suite/galera/t/galera_encrypt_tmp_files.cnf | 8 +++ .../suite/galera/t/galera_encrypt_tmp_files.test | 57 +++++++++++++++++++ sql/mf_iocache_encr.cc | 4 +- unittest/sql/mf_iocache-t.cc | 65 ++++++++++++++++++++++ 5 files changed, 167 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result b/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result new file mode 100644 index 00000000000..63f6c281af1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result @@ -0,0 +1,35 @@ +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +CREATE TABLE `t1` ( +`col1` int(11) NOT NULL, +`col2` varchar(64) NOT NULL DEFAULT '', +`col3` varchar(32) NOT NULL DEFAULT '0', +`col4` varchar(64) NOT NULL DEFAULT '', +`col5` tinyint(4) NOT NULL DEFAULT '0', +`col6` int(11) NOT NULL DEFAULT '0', +`col7` varchar(64) NOT NULL DEFAULT '', +`col8` tinyint(4) NOT NULL DEFAULT '0', +`col9` tinyint(4) NOT NULL DEFAULT '0', +`col10` text NOT NULL, +`col11` varchar(255) NOT NULL DEFAULT '', +`col12` tinyint(4) NOT NULL DEFAULT '1' +) ; +create table t2 (test int); +insert into t2 values (1); +drop table t1,t2; diff --git a/mysql-test/suite/galera/t/galera_encrypt_tmp_files.cnf b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.cnf new file mode 100644 index 00000000000..0f7f80b7d0b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.cnf @@ -0,0 +1,8 @@ +!include ../galera_2nodes.cnf +[mysqld] + +encrypt-tmp-files = 1 +plugin-load-add= @ENV.FILE_KEY_MANAGEMENT_SO +file-key-management +loose-file-key-management-filename= @ENV.MYSQL_TEST_DIR/std_data/keys.txt +log-bin diff --git a/mysql-test/suite/galera/t/galera_encrypt_tmp_files.test b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.test new file mode 100644 index 00000000000..c42c3dbd98a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_encrypt_tmp_files.test @@ -0,0 +1,57 @@ +# This file tests that mariadb cluster should not crash when encrypt_tmp_file +# is enabled + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +--connection node_1 + +CREATE TABLE `t1` ( + `col1` int(11) NOT NULL, + `col2` varchar(64) NOT NULL DEFAULT '', + `col3` varchar(32) NOT NULL DEFAULT '0', + `col4` varchar(64) NOT NULL DEFAULT '', + `col5` tinyint(4) NOT NULL DEFAULT '0', + `col6` int(11) NOT NULL DEFAULT '0', + `col7` varchar(64) NOT NULL DEFAULT '', + `col8` tinyint(4) NOT NULL DEFAULT '0', + `col9` tinyint(4) NOT NULL DEFAULT '0', + `col10` text NOT NULL, + `col11` varchar(255) NOT NULL DEFAULT '', + `col12` tinyint(4) NOT NULL DEFAULT '1' +) ; + +#Although we just need $counter >= 907 for IO_CACHE to use +#encrypted temp file. Just on safe side I am using $counter +# = 1100 +--disable_query_log +--let $counter=1100 +--let $query= (1,'test','test','test',0,0,'-1',0,0,'','',-1) +while($counter) +{ + --let $query= $query ,(1,'test','test','test',0,0,'-1',0,0,'','',-1) + --dec $counter +} +--let $query= INSERT INTO t1 values $query ; +--eval $query +--enable_query_log +#INSERT INTO `t1` VALUE + +create table t2 (test int); +insert into t2 values (1); + +drop table t1,t2; diff --git a/sql/mf_iocache_encr.cc b/sql/mf_iocache_encr.cc index 149e6feb605..f26a437a25a 100644 --- a/sql/mf_iocache_encr.cc +++ b/sql/mf_iocache_encr.cc @@ -49,8 +49,8 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count) if (pos_in_file == info->end_of_file) { - info->read_pos= info->read_end= info->buffer; - info->pos_in_file= pos_in_file; + /* reading past EOF should not empty the cache */ + info->read_pos= info->read_end; info->error= 0; DBUG_RETURN(MY_TEST(Count)); } diff --git a/unittest/sql/mf_iocache-t.cc b/unittest/sql/mf_iocache-t.cc index 31f98562521..6cfd4ca3551 100644 --- a/unittest/sql/mf_iocache-t.cc +++ b/unittest/sql/mf_iocache-t.cc @@ -187,6 +187,67 @@ void mdev9044() close_cached_file(&info); } +/* 2 Reads in cache makes second read to fail (only if first read uses temp file) */ +void mdev10259() +{ + int res; + uchar buf[CACHE_SIZE + 200]; + memset(buf, FILL, sizeof(buf)); + + diag("MDEV-10259- mysqld crash with certain statement length and order with" + " Galera and encrypt-tmp-files=1"); + + init_io_cache_encryption(); + + res= open_cached_file(&info, 0, 0, CACHE_SIZE, 0); + ok(res == 0, "open_cached_file" INFO_TAIL); + + res= my_b_write(&info, buf, sizeof(buf)); + ok(res == 0 && info.pos_in_file == CACHE_SIZE, "large write" INFO_TAIL); + + res= my_b_flush_io_cache(&info, 1); + ok(res == 0, "flush" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit READ_CACHE" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == CACHE_SIZE, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 200, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit WRITE_CACHE" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == CACHE_SIZE, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 200, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= my_b_fill(&info); + ok(res == 0, "fill" INFO_TAIL); + + res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0); + ok(res == 0, "reinit WRITE_CACHE" INFO_TAIL); + + res= my_b_read(&info, buf, sizeof(buf)) || data_bad(buf, sizeof(buf)); + ok(res == 0 && info.pos_in_file == CACHE_SIZE, "large read" INFO_TAIL); + + close_cached_file(&info); + +} + int main(int argc __attribute__((unused)),char *argv[]) { MY_INIT(argv[0]); @@ -202,6 +263,10 @@ int main(int argc __attribute__((unused)),char *argv[]) /* regression tests */ mdev9044(); + encrypt_tmp_files= 1; + mdev10259(); + encrypt_tmp_files= 0; + my_end(0); return exit_status(); }
1 0
0 0
[Commits] eb3e9cd: MDEV-15813 ASAN use-after-poison in hp_hashnr upon HANDLER READ on a versioned HEAP table.
by holyfoot@askmonty.org 08 May '18

08 May '18
revision-id: eb3e9cdbe86b5a68c3ec8a9f26165259e4ca7eec (mariadb-10.3.6-125-geb3e9cd) parent(s): bd09c5ca866e273b6cebbd9a15c51c82bfa3ac9b committer: Alexey Botchkov timestamp: 2018-05-08 14:19:55 +0400 message: MDEV-15813 ASAN use-after-poison in hp_hashnr upon HANDLER READ on a versioned HEAP table. Returns an error if we try to use a key in a query it declared unable to handle. --- mysql-test/suite/heap/heap_hash.result | 19 +++++++++++++++++++ mysql-test/suite/heap/heap_hash.test | 18 ++++++++++++++++++ sql/share/errmsg-utf8.txt | 2 ++ sql/sql_handler.cc | 29 +++++++++++++++++++++++++---- sql/sql_handler.h | 3 ++- sql/sql_prepare.cc | 1 + 6 files changed, 67 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/heap/heap_hash.result b/mysql-test/suite/heap/heap_hash.result index 55d4358..cba39c1 100644 --- a/mysql-test/suite/heap/heap_hash.result +++ b/mysql-test/suite/heap/heap_hash.result @@ -467,3 +467,22 @@ c1 bar2 DROP TABLE t1; End of 5.5 tests +# +# MDEV-15813 ASAN use-after-poison in hp_hashnr upon +# HANDLER READ on a versioned HEAP table +# +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, CONSTRAINT PRIMARY KEY (a, b), UNIQUE ba(b, a) USING HASH) ENGINE=HEAP; +INSERT INTO t1 VALUES (1, 10), (2, 20), (3,30), (4,40); +HANDLER t1 OPEN AS m; +HANDLER m READ `PRIMARY`= (3,30); +a b +3 30 +HANDLER m READ `PRIMARY`> (3,30); +ERROR HY000: HASH index `PRIMARY` does not support this operation +HANDLER m READ `ba`= (30,3); +a b +3 30 +HANDLER m READ `ba`= (30); +ERROR HY000: HASH index `ba` does not support this operation +HANDLER m CLOSE; +DROP TABLE t1; diff --git a/mysql-test/suite/heap/heap_hash.test b/mysql-test/suite/heap/heap_hash.test index 3fe95e1..5a08c6d 100644 --- a/mysql-test/suite/heap/heap_hash.test +++ b/mysql-test/suite/heap/heap_hash.test @@ -347,3 +347,21 @@ SELECT * FROM t1 WHERE c1='bar2'; DROP TABLE t1; --echo End of 5.5 tests + +--echo # +--echo # MDEV-15813 ASAN use-after-poison in hp_hashnr upon +--echo # HANDLER READ on a versioned HEAP table +--echo # + +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, CONSTRAINT PRIMARY KEY (a, b), UNIQUE ba(b, a) USING HASH) ENGINE=HEAP; +INSERT INTO t1 VALUES (1, 10), (2, 20), (3,30), (4,40); +HANDLER t1 OPEN AS m; +HANDLER m READ `PRIMARY`= (3,30); +--error ER_KEY_DOESNT_SUPPORT +HANDLER m READ `PRIMARY`> (3,30); +HANDLER m READ `ba`= (30,3); +--error ER_KEY_DOESNT_SUPPORT +HANDLER m READ `ba`= (30); +HANDLER m CLOSE; +DROP TABLE t1; + diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index c55ac4f..7446a60 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7915,3 +7915,5 @@ ER_UPDATED_COLUMN_ONLY_ONCE eng "The column %`s.%`s cannot be changed more than once in a single UPDATE statement" ER_EMPTY_ROW_IN_TVC eng "Row with no elements is not allowed in table value constructor in this context" +ER_KEY_DOESNT_SUPPORT + eng "%s index %`s does not support this operation" diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 09883d8..12e4b5a 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -618,7 +618,7 @@ static SQL_HANDLER *mysql_ha_find_handler(THD *thd, const LEX_CSTRING *name) static bool mysql_ha_fix_cond_and_key(SQL_HANDLER *handler, enum enum_ha_read_modes mode, const char *keyname, - List<Item> *key_expr, + List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode, Item *cond, bool in_prepare) { THD *thd= handler->thd; @@ -661,12 +661,30 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler, key_part_map keypart_map; uint key_len; + if (ha_rkey_mode != HA_READ_KEY_EXACT && + (table->file->index_flags(handler->keyno, 0, TRUE) & + (HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE)) == 0) + { + my_error(ER_KEY_DOESNT_SUPPORT, MYF(0), + table->file->index_type(handler->keyno), keyinfo->name); + return 1; + } + if (key_expr->elements > keyinfo->user_defined_key_parts) { my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), keyinfo->user_defined_key_parts); return 1; } + else if (key_expr->elements < keyinfo->user_defined_key_parts && + (table->file->index_flags(handler->keyno, 0, TRUE) & + HA_ONLY_WHOLE_INDEX)) + { + my_error(ER_KEY_DOESNT_SUPPORT, MYF(0), + table->file->index_type(handler->keyno), keyinfo->name); + return 1; + } + for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++) { my_bitmap_map *old_map; @@ -841,7 +859,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, goto err0; // mysql_lock_tables() printed error message already } - if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr, cond, 0)) + if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr, + ha_rkey_mode, cond, 0)) goto err; mode= handler->mode; keyno= handler->keyno; @@ -1002,14 +1021,16 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables, enum enum_ha_read_modes mode, const char *keyname, - List<Item> *key_expr, Item *cond) + List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode, + Item *cond) { SQL_HANDLER *handler; DBUG_ENTER("mysql_ha_read_prepare"); if (!(handler= mysql_ha_find_handler(thd, &tables->alias))) DBUG_RETURN(0); tables->table= handler->table; // This is used by fix_fields - if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr, cond, 1)) + if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr, + ha_rkey_mode, cond, 1)) DBUG_RETURN(0); DBUG_RETURN(handler); } diff --git a/sql/sql_handler.h b/sql/sql_handler.h index ffefec9..4c16f7e 100644 --- a/sql/sql_handler.h +++ b/sql/sql_handler.h @@ -80,5 +80,6 @@ void mysql_ha_rm_temporary_tables(THD *thd); SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables, enum enum_ha_read_modes mode, const char *keyname, - List<Item> *key_expr, Item *cond); + List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode, + Item *cond); #endif diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f763613..d6d30f7 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2204,6 +2204,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt, if (!(ha_table= mysql_ha_read_prepare(thd, tables, lex->ha_read_mode, lex->ident.str, lex->insert_list, + lex->ha_rkey_mode, lex->select_lex.where))) DBUG_RETURN(1);
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • ...
  • 1461
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.